It is usual when writing a list of items to separate each item with a comma, except the last two items, which are separated with the word "and". I recently needed to implement a function that took a string and converted it into a list of this type so I thought I would expand on it and post it here.
The function takes a single parameter, which can either be an array or a comma separated string. If an array is passed to the function then it is converted into a comma separated string and then passed onto the next part in the function. The function then removes any trailing commas, any commas that have nothing in between them and then makes sure that each comma has a single space after it. The final step is to replace the last comma with the word "and". Once the manipulation is complete then the resulting string is returned. If the string (after removing any trailing commas) doesn't contain any commas then it is simply returned.
Here is the function in full, will comments for each step.
/**
* This function will take a string in the format of a single item or
* multiple items in the format 1,2,3,4,5 or an array of items.
* The output will be a readable set of items with the last two items
* separated by " and ".
*
* @param string|array $numbers The list of items as a string or array.
* @return string The formatted items.
*/
function formatItems($numbers)
{
if (is_array($numbers)) {
// If numbers is an array then implode it into a comma separated string.
$numbers = implode(',', $numbers);
}
if (is_string($numbers)) {
// Make sure all commas have a single space character after them.
$numbers = preg_replace("/(\s*?,\s*)/", ", ", $numbers);
// Remove any spare commas
$numbers = preg_replace("/(,\s)+/", ", ", $numbers);
// The string contains commas, find the last comma in the string.
$lastCommaPos = strrpos($numbers, ',') - strlen($numbers);
// Replace the last ocurrance of a comma with " and "
$numbers = substr($numbers, 0, $lastCommaPos) . str_replace(',', ' and', substr($numbers, $lastCommaPos));
}
return $numbers;
}
Here are a few examples of this function in action.
echo formatItems('1');
echo formatItems('1,2');
echo formatItems('1,2,3,4,5,6,7');
echo formatItems(range(1,6));
echo formatItems(range('a','g'));
echo formatItems('sdfgdf g,sdf, g,dfg,df,g ,df g,df,g ,d fg');
echo formatItems('1.45/76,5/,85/6.,45./6,456');
echo formatItems('sdfah, ,,, ,, ,,,, , , , 568776ythU~O@)_}_:{>9l,65653224,253,4,236,56,98./,978/59');
echo formatItems('4575,8 56,456,36,45656 ,, , 4, 56, 546, 546, , 6, 456, , ');
This code produces the following output.
1
1 and 2
1, 2, 3, 4, 5, 6 and 7
1, 2, 3, 4, 5 and 6
a, b, c, d, e, f and g
sdfgdf g, sdf, g, dfg, df, g, df g, df, g and d fg
1.45/76, 5/, 85/6., 45./6 and 456
sdfah, 568776ythU~O@)_}_:{>9l, 65653224, 253, 4, 236, 56, 98./ and 978/59
4575, 8 56, 456, 36, 45656, 4, 56, 546, 546, 6 and 456
UPDATE: 08/05/2010
Thanks to Carl for finding a little bug with regards to how commas in messy strings are looked at within the function. I had a quick look at code I wrote to clean up a list of user inputted items and included it in this code. Here is the new version of the function.
/**
* This function will take a string in the format of a single item or
* multiple items in the format 1,2,3,4,5 or an array of items.
* The output will be a readable set of items with the last two items
* separated by " and ".
*
* @param string|array $numbers The list of items as a string or array.
* @return string The formatted items.
*/
function formatItems($numbers)
{
if (is_array($numbers)) {
// If numbers is an array then implode it into a comma separated string.
$numbers = implode(',', $numbers);
}
if (is_string($numbers)) {
/*
Make sure all commas have a single space character after them and that
there are no double commas in the string.
*/
$numbers = trim($numbers);
$patterns[0] = '/\s*,\s*/';
$patterns[1] = '/,{2,}/';
$patterns[2] = '/,+$/';
$patterns[3] = '/^,+/';
$patterns[4] = '/,/';
$replacements[0] = ',';
$replacements[1] = ',';
$replacements[2] = '';
$replacements[3] = '';
$replacements[4] = ', ';
$numbers= preg_replace($patterns, $replacements, $numbers);
// The string contains commas, find the last comma in the string.
$lastCommaPos = strrpos($numbers, ',') - strlen($numbers);
// Replace the last ocurrance of a comma with " and "
$numbers = substr($numbers, 0, $lastCommaPos) . str_replace(',', ' and ', substr($numbers, $lastCommaPos));
}
return $numbers;
}
Comments
Submitted by Carl on Sat, 05/08/2010 - 20:03
PermalinkSubmitted by giHlZp8M8D on Sat, 05/08/2010 - 22:23
Permalink$list = formatItems($assignees);
might work but i'm not having any luck. the $assignees variable is a text array. thanks!!Submitted by john on Thu, 05/20/2010 - 13:55
PermalinkSubmitted by giHlZp8M8D on Thu, 05/20/2010 - 22:30
PermalinkSubmitted by neurotopia on Thu, 05/20/2010 - 23:03
PermalinkSubmitted by giHlZp8M8D on Fri, 05/21/2010 - 09:11
PermalinkSubmitted by neurotopia on Sun, 05/23/2010 - 02:50
PermalinkSubmitted by neurotopia on Sun, 05/23/2010 - 02:54
PermalinkSubmitted by neurotopia on Sun, 05/23/2010 - 20:28
PermalinkSubmitted by giHlZp8M8D on Sun, 05/23/2010 - 21:42
PermalinkHi Phil,
Thanks heaps for this! I was wondering if you might be able to help me with something similar - I want to automatically create list items <li> when ever some enters a line break. So when the user enters
Item 1
Item2
Item3
The script changes it to:
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
Any idea of how I would go about this? Thanks heaps!
Submitted by Adam on Tue, 12/13/2011 - 13:09
PermalinkShould be quite simple. All you need to do is replace line breaks with the string '</li><li>' and then wrap the whole thing in a list item to ensure the correct markup.
Submitted by giHlZp8M8D on Tue, 12/13/2011 - 16:32
PermalinkAdd new comment