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

Just wondering if I can do something like this or if i'm stuck using while...

$gah = join('<br>', map {"$key = $value"} (($key, $value) = each %somehash));

Replies are listed 'Best First'.
(jeffa) Re: map and each?
by jeffa (Bishop) on May 27, 2002 at 02:17 UTC
    Sure, but you have to use keys instead of each:
    my $gah = join ('', map {"$_ = $hash{$_}<br>"} keys %hash);
    I moved the <br> inside the map so that each pair will get one - put it back where you had it if you do not want a <br> tag on the last pair.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: map and each?
by educated_foo (Vicar) on May 27, 2002 at 02:18 UTC
    Unless you wait for perl6, you're stuck. But really, what's so bad about:
    $gah = join(', ', map { "$_ = $hash{$_}" } keys %hash); # or push @gah, "$k = $v" while (my ($k, $v) = each %hash); $gah = join(', ', @gah);
    /s
    Update: Here's what you want! ;)
    $gah = join ', ', map { join ' = ', each %hash } 1..keys %hash;
      Because here's my real problem:

      sub genHash { my $hashn = shift; return "\%$hashn = (\n" . join(",\n", map { $key = $_; "'$key' => " . (ref $$hashn{$_} ? '{' . join(",\n", map { "'$_' => qq~" . safeTilde($$hashn{$key}->{$_}) . '~' } keys %{$$hashn{$key}}) . '}' : 'qq~' . safeTilde($$hashn{$key}) . '~' ) } keys %$hashn) . ");\n"; } sub safeTilde { my $code = shift; $code =~ s/\~/\\~/g; return $code; }
      then you would call it by genHash(\%somehash)

      though it does work, it's just is a little long and messy..

      Oh, by the way, it takes a hash and generates the perl to re-create it :)

      Edit kudra, 2002-05-27 s/pre/code

        Oh, by the way, it takes a hash and generates the perl to re-create it :)

        Have you tried Data::Dumper?

        It excels at what you're trying to do, and can stringify all sorts of Perl data structures in addition to hashes.

        use Data::Dumper; my $foo = Data::Dumper->Dump( [ \%ENV ], [qw( ENV )] );

            --k.


        Oh, by the way, it takes a hash and generates the perl to re-create it :)
        As long as the value doesn't contain dollar signs or at-signs or backslashes, since you used qq instead of q. Oh, and the key can't contain any single quotes.

        I agree with the other poster: don't reinvent Data::Dumper without understanding everything it does first.

        -- Randal L. Schwartz, Perl hacker

      ++ for creative use of the .. operator. :-)
      ____________

      Makeshifts last the longest.
Re: map and each?
by dug (Chaplain) on May 27, 2002 at 02:33 UTC
    Well, your not stuck :)
    You do have an error, however.

    perldoc -f each says in it's first paragraph:
    When called in list context, returns a 2-element list
    consisting of the key and value for the nextelement of
    a hash, so that you can iterate overit.  When called 
    in scalar context, returns only the key for the next
    element in the hash.
    

    This causes an error in your code that means it will only join the first key and value of your hash (you're calling in list context).

    One of the many ways you can accomplish what you are trying to (I think) is this:
    my $joined; foreach my $key ( keys( %hash ) ) { $joined .= "$key = $hash{$key}<br>"; }
    This approxomates the functionality that you display above (key = value<br>key = value<br> etc. all in one string) without the error.

    I'm certain some of the other monks will have other suggestions. Anything involving Perl and a question asking if i'm stuck is too much for some folk around here to resist.

    Dug
Re: map and each?
by mephit (Scribe) on May 27, 2002 at 02:48 UTC
    my $gah = join ('<br>', map {"$_ = $somehash{$_}"} keys %somehash);
    Does that do what you want? I don't know why the quotes around the entire expression are necessary, though, or if they're a Bad Idea for any reason. (For that matter, *why* is quoting a scalar a Bad Idea? Or is it just "useless?")

    --

    There are 10 kinds of people -- those that understand binary, and those that don't.

      The quotes are necessary here for variable interpolation which, according to The Camel(sec. ed.), is "really just a handy form of string concatenation". Try this instead:
      my $gah = join ("<br>", map {'$_ = $somehash{$_}'} keys %somehash);
      Big difference. Generally, double quoting scalars is a Bad Idea only if it is "useless". I see a lot of newbies trying silly things like:
      my $first = "Hello World\n"; my $second = "$first"; print "$second";
      Only the first set of double quotes are necessary for the special character "\n". So ,what harm is done with that example? None, but this behaviour usually stems from Cargo Cult Programming, and that's why it's a Bad Idea. Double quotes are good when used responsibly. Irresponsible use will lead to mistakes like thinking that an object ref is a scalar:
      use strict; use CGI; my $q = CGI->new(); print "$q->param('foo')\n"; # wrong print $q->param('foo'),"\n"; # right print $q->param('foo')."\n"; # right print "@{[$q->param('foo')]}\n" # right, but twisted ;)

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      B--B--B--B--B--B--B--B--
      H---H---H---H---H---H---
      (the triplet paradiddle with high-hat)