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

I have this piece of code but I feel it is clunky. Basically, all I want is to chomp each array element, substitute "d" with some new value and join all the elements by a comma. Below is my code.

#!/usr/bin/perl use strict; my @a = qw( a b c d ); my @z; for (@a) { chomp; s/(d)/new(\1)/; push ( @z, $_ ); } print join ",", @z;
Here's the output of this code.
a ,b ,c , new(d)

I hoping to do the above output in a one liner, but I can't just figure it out. Here's what I've started...
print join ", ", map { chomp; s/(d)/new(\1)/ } @a;

Thanks.

Replies are listed 'Best First'.
Re: Better Way of Manipulating Array Elements
by morgon (Priest) on May 19, 2009 at 21:50 UTC
    print join ", ", map { chomp; s/(d)/new($1)/; $_ } @a;

      Since it appears to be a complete program, the following would do:

      perl -pe'chomp; s/(d)/new($1)/; s/^/,/ if $.-1'

      I first considered the following, but it leaves a trailing comma and no LF at file's end:

      perl -pl54e's/(d)/new($1)/'
        You are missing that he want's a blanks after the commas. And I improve (golfwise) to:

        perl -pe's/(d)/new($1)/; s/\n/, / unless eof'

        But since capturing a literal regex is silly anyway, the best I can think of at the moment is

        perl -pe's/d/new(d)/;s/\n/, / unless eof'
      Alternate fix:
      use List::MoreUtils qw( apply ); print join ", ", apply { chomp; s/(d)/new($1)/ } @a;
      Thanks!!! That did the trick.
Re: Better Way of Manipulating Array Elements
by JavaFan (Canon) on May 19, 2009 at 22:32 UTC
    Don't use \1 in the replacement part. It's a kludge, ambigious, only works for small numbers, may no longer work in a future version of Perl, will warn when warnings are enabled, and will mark you as an old perl4 programmer who is having sed-withdrawal syndromes.

    As for substituting "d", do you mean:

    1. Replace "d" only if an array element is "d" - that is, "abcded" should remain as is.
    2. Any "d" in any array element should be replaced with "newd", so "abcded" becomes "abcnewdenewd".
    3. Only the first "d" in any array element should be replaced with "newd", so "abcded" becomes "abcnewded". This is what your current code does.
Re: Better Way of Manipulating Array Elements
by LanX (Saint) on May 19, 2009 at 22:06 UTC
    the resulting listelements of a map are formed by the last command in the block, in your case it's the return value of s/// !

    "Searches a string for a pattern, and if found, replaces that pattern with the replacement text and returns the number of substitutions made. Otherwise it returns false (specifically, the empty string)."

    Did you notice that you also manipulated @a by the way?

    "Note that $_ is an alias to the list value" (from map)

    ...so @a holds the list you wanted 8 )

    Cheers Rolf

    UPDATE: I'd rather preferre something like this  map { /(d)/ ? "new($1)" : $_ } @a