5
\$\begingroup\$

I wrote the below method to list out the elements of an array, as well as adding the Oxford comma to the list if desired. However, my for-loop looks, perhaps, a little convoluted. Is there a better way to handle clearly both the Oxford comma and the ability to add a conjunction?


function listOut($array = array(), $oxford = false, $conjunction = 'and') {
 $count = is_array($array) ? count($array) : 0;
 switch($count) {
 case 0: // Either not an array or an empty array
 return '';
 case 1: // Only one element in the array, return it
 return $array[0];
 case 2: // Two elements; join them together with the conjunction
 return "{$array[0]} {$conjunction} {$array[1]}";
 default: // At least two elements, join with commas and conjunction
 $s = ", ";
 $t = "";
 for($i = 0; $i < $count; $i++) {
 // Add a conjunction if it's the last element in the array
 if($i + 1 === $count) {
 $s = $oxford ? $s . "$conjunction " : " $conjunction ";
 }
 // Only prepend comma if not the first element
 if($i > 0) { 
 $t .= $s;
 }
 // Add the element to the return string
 $t .= $array[$i];
 }
 return $t;
 }
}
$array1 = array('orange');
$array2 = array('white', 'gold');
$array3 = array('black', 'white', 'purple');
echo listOut($array1); // orange
echo listOut($array2); // white and gold
echo listOut($array3); // black, white and purple
echo listOut($array1, true); // orange
echo listOut($array2, true); // white and gold
echo listOut($array3, true); // black, white, and purple
asked Sep 30, 2014 at 16:51
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

You can effectively get rid of the switch statement as well as the is_array check in the count ternary if you do the check in the beginning (and exit early at that - so not wasting any cycles).

You can also get rid of

# Only prepend comma if not the first element
if($i > 0) { 
 $output .= $separator;
}

If you add a ternary concat to $output (at the expense of gaining 2 opcode calls over the if/else). This would be the function after cleaning it:

function listOut($array = array(), $oxford = false, $conjunction = 'and', $separator = ", ") {
 if(!is_array($array)){ # We're expecting an array 
 return false;
 }
 $count = count($array) ?: 0;
 $output = "";
 if($count == 2){ return implode(" $conjunction ", $array); }
 for($i = 0; $i < $count; $i++) {
 # Add a conjunction if it's the last element in the array
 if($i + 1 === $count) {
 $separator = $oxford ? $separator . "$conjunction " : " $conjunction ";
 }
 # Add the element to the return string
 $output .= ($i > 0 ? $separator : "") . $array[$i];
 }
 return $output;
}

and the test outputs:

$array = 'blue';
$array1 = array('orange');
$array2 = array('white', 'gold');
$array3 = array('black', 'white', 'purple');
$array4 = array('black', 'white', 'purple', 'gold');
echo listOut($array) . "<br>";
echo listOut($array1) . "<br>"; // orange
echo listOut($array2) . "<br>"; // white and gold
echo listOut($array3, true) . "<br>"; // black, white and purple
echo listOut($array4) . "<br>"; // black, white and purple

Results:

false
orange
white and gold
black, white, and purple
black, white, purple and gold
answered Sep 30, 2014 at 19:19
\$\endgroup\$
4
  • \$\begingroup\$ I like a lot of the optimizations you've done! However, an Oxford comma would appear in a two-element array in this case ("white, and gold"). \$\endgroup\$ Commented Sep 30, 2014 at 19:36
  • \$\begingroup\$ Ah! Didn't test that. To solve that issue, just add if($count == 2){ return implode(" $conjunction ", $array); } after $count = count($array) ?: 0. \$\endgroup\$ Commented Sep 30, 2014 at 19:46
  • \$\begingroup\$ Sounds good (and I actually made another modification to that by checking $count <= 2). Now I'll be able to list out items for perfectly peaceful purposes. Thank you! \$\endgroup\$ Commented Sep 30, 2014 at 19:53
  • \$\begingroup\$ Good catch on the <=: exit early, exit often! \$\endgroup\$ Commented Sep 30, 2014 at 20:01

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.