Given a list as an argument, construct a proper English string of one of the forms:
sub and_a_list { if (@_ > 2) { join ", ", @_[0..$#_-1], " and $_[-1]" } elsif (@_ > 1) { "$_[0] and $_[1]" } elsif (@_ > 0) { $_[0] } else { "" } }

Replies are listed 'Best First'.
RE: Format a list with commas and
by davorg (Chancellor) on Aug 24, 2000 at 11:55 UTC

    I was always taught that the correct way of printing lists like that was "A, B, C and D" (i.e. no comma before the "and"). If your English teacher was like mine then this version will work better for you:

    sub and_a_list { if (@_ > 2) { join(", ", @_[0..$#_-1]) . " and $_[-1]" } elsif (@_ > 1) { "$_[0] and $_[1]" } elsif (@_ > 0) { $_[0] } else { "" } }
    --
    <http://www.dave.org.uk>

    European Perl Conference - Sept 22/24 2000, ICA, London
    <http://www.yapc.org/Europe/>

      That particular lie was propogated by newspaper publishers who thought they could save millions by dropping all those "extra" commas. Leaving the last commas off makes for a lot more ambiguity. Unfortunately, many academics got convinced that if newspapers write that way it must be a good idea.

      My favorite breakfasts are bacon and eggs, blueberry muffins, and sausage and biscuits. Take one, two or three times daily.

              - tye (but my friends call me "Tye")
        Thanks for that little bit of brain lint.
        I always "corrected" myself. I wondered why it never looked
        right to me.
      If you don't want that comma, you can do without the cases:
      sub list { join ", " => @_ [0 .. $#_ - 2], join " and " => @_ [grep {$_ >= 0} $#_ - 1, $#_] }

      Abigail

        sub list { join(" and ", reverse grep defined && length, pop @_, join(", ", @ +_)) }

        Makeshifts last the longest.

RE: Format a list with commas and
by Anonymous Monk on Sep 27, 2000 at 13:49 UTC
    sub and_a_list { my $r = join(', ', @_); my $pos = rindex($r, ', '); substr($r, $pos, 2) = ' and ' if $pos > -1; $r; }
    The everything is the same except the last element problem seems to come up quite a bit; my approach is generally to do the same thing to them all and then "fixup" the last one. summer
RE: Format a list with commas and 'and'
by turnstep (Parson) on Aug 30, 2000 at 20:29 UTC

    My version. What can I say, I like the ? : operator :)

    Usage: &print_with_ands(\@array);

    sub print_with_ands { my $x=0; my $a=shift; printf "$a->[$x-1]%s", defined $a->[$x+1] ? ", " : ! defined $a->[$x] ? "\n" : $x==1 ? " and " : ", and " while defined $a->[$x++]; }
Re: Format a list with commas and "and"
by jinxdidnt (Initiate) on Oct 02, 2002 at 06:04 UTC
    sub serial(@) { join(', ', @_[0..$#_-1]) . (@_>2 ? ',':'' ) . (@_>1 ? (' and ' . $_[-1]) : $_[-1]); }

      Hey! You can't see the join's :)

      #! perl -sw use strict; sub npAndAList{$"=', '; return unless @_; @_==1 and "@_" or "@_[0 .. $ +#_-1] and $_[-1]" } print npAndAList(qw(a b c d e)[0..$_]),$/ for -1..4; __DATA__ a a and b a, b and c a, b, c and d a, b, c, d and e

      Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
what about using $" ?
by harleypig (Monk) on Jun 27, 2005 at 00:23 UTC

    What about this?

    sub andify { return '' unless @_; return $_[0] if @_ == 1; local $" = @_ == 2 ? ' ' : ', '; $_[-1] = 'and ' . $_[-1]; return "@_"; }
    Fixed squiggly brackets and should be $" not $,.
    Fixed comma placement.
    Got rid of blackberry comment.
    Handled null case.
    Changed regex to concatenation
    Harley J Pig

    20050525 Edit by ysth: p, code tags