# Recipe 4.2 Printing a List with Commas

#### 4.2.1 Problem

You'd like to print out a list containing an unknown number of elements, placing an "and" before the last element and commas between each element if there are more than two.

#### 4.2.2 Solution

Use this function, which returns the formatted string:

sub commify_series {
(@_ =  = 0) ? ''                                      :
(@_ =  = 1) ? \$_[0]                                   :
(@_ =  = 2) ? join(" and ", @_)                       :
join(", ", @_[0 .. (\$#_-1)], "and \$_[-1]");
}

#### 4.2.3 Discussion

It often looks odd to print out arrays:

@array = ("red", "yellow", "green");
print "I have ", @array, " marbles.\n";
print "I have @array marbles.\n";
I have redyellowgreen marbles.
I have red yellow green marbles.

What you really want it to say is, "I have red, yellow, and green marbles". The function given in the solution generates strings in that format. The word "and" is placed between the last two list elements. If there are more than two elements in the list, a comma is placed between every element.

Example 4-1 gives a complete demonstration of the function, with one addition: if any element in the list already contains a comma, a semicolon is used for the separator character instead.

##### Example 4-1. commify_series
#!/usr/bin/perl -w
# commify_series - show proper comma insertion in list output

# @lists is an array of (references to anonymous) arrays
@lists = (
[ 'just one thing' ],
[ qw(Mutt Jeff) ],
[ qw(Peter Paul Mary) ],
[ 'To our parents', 'Mother Theresa', 'God' ],
[ 'pastrami', 'ham and cheese', 'peanut butter and jelly', 'tuna' ],
[ 'recycle tired, old phrases', 'ponder big, happy thoughts' ],
[ 'recycle tired, old phrases',
'ponder big, happy thoughts',
'sleep and dream peacefully' ],
);

foreach \$aref (@lists) {
print "The list is: " . commify_series(@\$aref) . ".\n";
}
# demo for single list
@list = qw(one two three);
print "The last list is: " . commify_series(@list) . ".\n";

sub commify_series {
my \$sepchar = grep(/,/ => @_) ? ";" : ",";
(@_ =  = 0) ? ''                                      :
(@_ =  = 1) ? \$_[0]                                   :
(@_ =  = 2) ? join(" and ", @_)                       :
join("\$sepchar ", @_[0 .. (\$#_-1)], "and \$_[-1]");
}

Here's the output from the program:

The list is: just one thing.
The list is: Mutt and Jeff.
The list is: Peter, Paul, and Mary.
The list is: To our parents, Mother Theresa, and God.
The list is: pastrami, ham and cheese, peanut butter and jelly, and tuna.
The list is: recycle tired, old phrases and ponder big, happy thoughts.
The list is: recycle tired, old phrases; ponder
big, happy thoughts; and sleep and dream peacefully.
The last list is: one, two, and three.

As you see, we don't follow the ill-advised practice of omitting the final comma from a series under any circumstances. To do so introduces unfortunate ambiguities and unjustifiable exceptions. The examples shown would have claimed that we were the offspring of Mother Teresa and God, and would have had us eating sandwiches made of jelly and tuna fish mixed together atop the peanut butter.

#### 4.2.4 See Also

Fowler's Modern English Usage; we explain the nested list syntax in Recipe 11.1; the grep function in perlfunc(1) and Chapter 29 of Programming Perl; the conditional operator ("?:") is discussed in perlop(1) and in the "Conditional Operator" section of Chapter 3 of Programming Perl

 Chapter 1. Strings
 Chapter 2. Numbers
 Chapter 3. Dates and Times
 Chapter 5. Hashes
 Chapter 6. Pattern Matching
 Chapter 7. File Access
 Chapter 8. File Contents
 Chapter 9. Directories
 Chapter 10. Subroutines
 Chapter 11. References and Records
 Chapter 12. Packages, Libraries, and Modules
 Chapter 13. Classes, Objects, and Ties
 Chapter 14. Database Access
 Chapter 15. Interactivity
 Chapter 16. Process Management and Communication
 Chapter 17. Sockets
 Chapter 18. Internet Services
 Chapter 19. CGI Programming
 Chapter 20. Web Automation
 Chapter 21. mod_perl
 Chapter 22. XML