myocom has asked for the wisdom of the Perl Monks concerning the following question:

There are, as with most things Perl, many ways to do this, but this begs for a simple solution. The ways I'm thinking of are fairly ugly.

Given an array, say:

@a = ('this', 'that', 'the other', 'the last thing');

How would you produce the output of: "I know about this, that, the other, and the last thing."


Bonus points: Now let's say that I only want three of those. Say, "I know about this, the other, and the last thing." Does that change your solution? I guess I'm trying to make this as general as possible, while still keeping it simple.

Replies are listed 'Best First'.
RE: Creating comma-delimited lists
by merlyn (Sage) on Aug 24, 2000 at 01:35 UTC
      I knew I should've checked Snippets first... :-)
Re: Creating comma-delimited lists
by BlaisePascal (Monk) on Aug 24, 2000 at 00:56 UTC
    You could use join ',',@list, but that wouldn't get you the "and" at the end...

    Untested code:

    @thingsicouldknow = ('this','that','the other','the last thing'); @iknowthat = (0,1,3); #this, that, and last thing # now print the things I know... @thingsiknow = @thingsicouldknow[@iknowthat]; print "I know about " print join(', ',@thingsiknow[0..@thingsiknow-2]); print ", and", @thingsiknow[-1] if @thingsiknow > 1; print ".\n".
    It's probably not the best, but it might work. Update:Fixed some off-by-one errors caused by using $#foo

    This version should not print the "and" if you only know one thing.

      I'm not sure I realized, for some reason, that you could do @thingsiknow = @thingsicouldknow[@iknowthat]. Sure beats the heck out of doing a foreach...push deal as I was doing in my script beforehand.

      Thanks for the tip!

RE: Creating comma-delimited lists
by Boogman (Scribe) on Aug 24, 2000 at 00:55 UTC
    Hows this...
    sub iknow { if ( @_ > 1 ) { print "I know about ", join( ', ', @_[0 .. @_ - 2] ), ", and $_[-1].\n"; } elsif ( @_ == 1 ) { print "I know about @_.\n"; } else { print "I don't know bout nuthin.\n"; } }
    Update: Oh, and if you just wanted to have it print certain elements, just pass it an array slice. For example,
    my @array = ( one, two, three, four, five ); iknow( @array[1, 3, 5] );
    should print out "I know about one, three, and five."
    Aha!
    by myocom (Deacon) on Aug 24, 2000 at 01:05 UTC

      Hey, now, that's the stuff! It was the @_ - 2 and $_[-1] that I couldn't quite pull out of the recesses of my brain.

      Thanks much!
RE: Creating comma-delimited lists
by Adam (Vicar) on Aug 24, 2000 at 00:56 UTC
    join ', ', @a
    Update: I just noticed the extra 'and' for the last thing, so:
    my $string = join ', ', @a[$[..$#a-1]; $string .= ", and $a[-1]"; # or in one line my $str = join ', ', @a[$[..$#a-1], "and $a[-1]";
    BlaisePascal makes the good point that this assumes a list of size greater then 1. This too can be solved easily:
    my $str = @a > 1 ? join ', ', @a[$[..$#a-1], "and $a[-1]" : $a[0];
Re: Creating comma-delimited lists
by mrmick (Curate) on Aug 24, 2000 at 23:05 UTC
    My 2 cents:
    @a = ('this', 'that', 'the other', 'the last thing'); $tmpstring=join(',',@a); $string = "I know about " . $tmpstring . "."; print $string;

    Mick
      This is the easy way, but it ignores the requirement to print "and" before the last known item. You would print "I know about this,that,the other,the last thing.", not "I know about this, that, the other, and the last thing.".
        It FIGURES that I would overlook that. Thank you, BlaisePascal, for spotting it. It's nice comments like yours that will help to keep me on my toes. :-)

        Well, in an attempt to redeem myself, here's an oversimplified (and crude)fix:

        @a = ('this', 'that', 'the other', 'the last thing'); $lastone=pop(@a); $tmpstring=join(',',@a); $string = "I know about $tmpstring, and $lastone."; print $string;

        Mick