It seems like it should be simple. Humans list things all the time. If you have more than two items, you separate all but the last two with commas, and then the last two with the word “and”. If you’re pedantic, you might throw in an Oxford comma.
I needed to do the same in PHP. Specifically, I have an array of people’s names, and I want to turn that into a list that gets dropped dynamically into a sentence.
Just converting an array to a comma-separated list is easy:
$list = implode(', ', $array);
But that won’t put the “and” in there. Sure, you could write some code that finds the last comma and replaces it with “and,” but what if a person’s name has a generation suffix with a comma? You don’t want your list to say “Betty Johnson, James Smith and Jr.” when it should say “Betty Johnson and James Smith, Jr.”
I wasn’t able to find a good solution out there, so here’s what I came up with. First I combine the value of the last element in the array with the second-to-last, and remove the last. Then I do the implode()
.
if (count($array) >= 2) { $array[count($array)-2] .= ' and ' . $array[count($array)-1]; unset($array[count($array)-1]); } $list = implode(', ', $array);
Note that you want to be sure that the array has at least two nodes before running the combination.
In case you’re thinking the implode()
is going to be an issue when the array includes exactly two nodes, remember that the conditional is running, inserting the “and” and turning it into a one-node array, so implode()
will just return the value of the single node, without the concatenation string.
Of course, if you want the Oxford comma, it’s going to be a bit more complicated. You’ll need a conditional that checks for three or more nodes and inserts “, and” in the combination of the last two nodes. Then of course you’d also keep the existing conditional for exactly two nodes, because you don’t want the comma if there are only two items in the list:
if (count($array) >= 3) { $array[count($array)-2] .= ', and ' . $array[count($array)-1]; unset($array[count($array)-1]); } elseif (count($array) == 2) { $array[count($array)-2] .= ' and ' . $array[count($array)-1]; unset($array[count($array)-1]); } $list = implode(', ', $array);