Add commas to items and with "and" near the end in PHP

minitech's solution on the outset is elegant, except for one small issue, his output will result in:

var_dump(makeList(array('a', 'b', 'c'))); //Outputs a, b and c

But the proper formatting of this list (up for debate) should be; a, b, and c. With his implementation the next to last attribute will never have ',' appended to it, because the array slice is treating it as the last element of the array, when it is passed to implode().

Here is an implementation I had, and properly (again, up for debate) formats the list:

class Array_Package
{
    public static function toList(array $array, $conjunction = null)
    {
        if (is_null($conjunction)) {
            return implode(', ', $array);
        }

        $arrayCount = count($array);

        switch ($arrayCount) {

            case 1:
                return $array[0];
                break;

            case 2:
                return $array[0] . ' ' . $conjunction . ' ' . $array[1];
        }

        // 0-index array, so minus one from count to access the
        //  last element of the array directly, and prepend with
        //  conjunction
        $array[($arrayCount - 1)] = $conjunction . ' ' . end($array);

        // Now we can let implode naturally wrap elements with ','
        //  Space is important after the comma, so the list isn't scrunched up
        return implode(', ', $array);
    }
}

// You can make the following calls

// Minitech's function
var_dump(makeList(array('a', 'b', 'c'))); 
// string(10) "a, b and c"

var_dump(Array_Package::toList(array('a', 'b', 'c')));
// string(7) "a, b, c"

var_dump(Array_Package::toList(array('a', 'b', 'c'), 'and'));
string(11) "a, b, and c"

var_dump(Array_Package::toList(array('a', 'b', 'c'), 'or'));
string(10) "a, b, or c"

Nothing against the other solution, just wanted to raise this point.


Here’s a function for that; just pass the array.

function make_list($items) {
    $count = count($items);

    if ($count === 0) {
        return '';
    }

    if ($count === 1) {
        return $items[0];
    }

    return implode(', ', array_slice($items, 0, -1)) . ' and ' . end($items);
}

Demo

Tags:

Php

Csv

Loops