http://qs321.pair.com?node_id=524164

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

Hi , I am storing huge number of variables in a hash.
my %replacehash; $replacehash{TEMP1} = "contains TEMP1"; $replacehash{TEMP2} = "contains TEMP2"; $replacehash{TEMP3} = "contains TEMP3"; $replacehash{TEMP4} = "contains TEMP4"; ....
where TEMP1,TEMP2,... are variables and the values are got using API's.but over here i have used some junk data. Is there elegant way of handling this ? instead of assigning each key with a value,i mean something like "foreach" loop? Thanks.

Replies are listed 'Best First'.
Re: elegant way of handling hash?
by g0n (Priest) on Jan 19, 2006 at 10:22 UTC
    The context of your problem is still not entirely clear. Still, this example does what you ask for:

    use strict; use warnings; my @methodcalls = qw (getExeName getTempName); my @getDataMethods = qw (getNameType); my $obj = Foo->new(); my %hash; my $counter=0; for my $call (@methodcalls) { $hash{"temp".$counter} = $obj->$call; $counter++; } for my $call (@getDataMethods) { $hash{"temp".$counter} = $obj->getData->$call; $counter++; } for (keys %hash) { print "$_\t $hash{$_}\n"; } package Foo; sub new { return bless \{}, shift; } sub getExeName { return "exename"; } sub getTempName { return "tempname"; } sub getData { return shift; } sub getNameType { return "nametype"; }

    Note that the getData->getNameType call has to be treated separately from the simple method calls. If you have other (possibly more complex) chained methods, you'll have to adapt the code to handle those as well (unless someone can think of a better way?)

    Update: As BrowserUK has said, the chained methods can be done with a string eval. It's a slow and ugly way of doing it, but it works:

    use strict; use warnings; my $obj = Foo->new(); my %hash; my $counter=0; my @methodcalls = qw (getExeName getTempName getData->getNameType); for my $call (@methodcalls) { my $evalstring = "\$obj->$call"; $hash{"temp".$counter} = eval($evalstring); $counter++; } for (keys %hash) { print "$_\t $hash{$_}\n"; }

    --------------------------------------------------------------

    "If there is such a phenomenon as absolute evil, it consists in treating another human being as a thing."

    John Brunner, "The Shockwave Rider".

Re: elegant way of handling hash?
by dorward (Curate) on Jan 19, 2006 at 09:38 UTC

    It mostly depends on how you get the data from the API. Its quite likely that a foreach loop (or a while loop) will get the job done, but not easy to say without knowing exactly how you are getting the data in the first place!

      hi doward, i will try to be more clear .
      my %replacehash; $replacehash{TEMP1} = $flow->getExeName(); $replacehash{TEMP2} = $flow->getTempName(); $replacehash{TEMP3} = $flow->getData()->getNameType(); ....
      All the API's are different .

        You can do the first two quite easily

        @replacehash{ map{ "TEMP$_" } 1 .. 2 } = map{ $flow->$_ } qw[getExeName getTempName];

        Doing the third one, with the double level of indirection, would probably require a string eval.

        Whether you should do this is another matter entirely. It would have to be a pretty long list to warrent it, and even then you would probably be better having the $flow class provide an API that returned the hash. That way the construction need only be done once and the user of the $flow object can just do

        my %replacehash = $flow->getAll();

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        You could try

        my %replacehash = ( TEMP1 => $flow->getExeName(), TEMP2 => $flow->getTempName(), TEMP3 => $flow->getData()->getNameType(), )
        (If you call a method with no arguments, like here, you could also omit the empty pair of parentheses, but that's not the point here.)

        Also

        my %replacehash; @replacehash{map { "TEMP$_" } 1 .. 3} = ( $flow->getExeName(), $flow->getTempName(), $flow->getData()->getNameType(), )
Re: elegant way of handling hash?
by blazar (Canon) on Jan 19, 2006 at 09:51 UTC
    my %replacementhash = map { $_="TEMP$_"; $_ => "contains $_"} 1..4;

    Seriously, it all really depends, on how you actually get the values, i.e. on your APIs. Probably a for or a while loop are the best way to go. Hard to tell anyway, without seeing real code...

Re: elegant way of handling hash?
by Anonymous Monk on Jan 19, 2006 at 09:52 UTC
    How do you define "variables"? How/what/means "are got using API"? Elegant way of what?
Re: elegant way of handling hash?
by mojotoad (Monsignor) on Jan 19, 2006 at 10:44 UTC
    I refer you to my exegesis.

    Cheers,
    Matt