in reply to Re^6: Combinations of lists, etc
in thread Combinations of lists to a hash

> What am I doing wrong, please?

The output looks right to me. You are assigning the same hashref again.

Do you need the hashes to different instances with same content?

Then you need to loop over all keys and always assign a new copy { %$hashref }

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Replies are listed 'Best First'.
Re^8: Combinations of lists, etc
by tel2 (Pilgrim) on Oct 07, 2019 at 20:48 UTC
    Thanks for that, LanX,

    "Do you need the hashes to different instances with same content?"
    If I understand your question correctly, then yes.  See example in update #2 of my original post.  It's a hash of a hash and the inner hashes have the same keys and values (for a given line of input data).

    After some more experimenting, since multiplying the right hand side (e.g. with 'x2') is not going to work (the reason for which still isn't clear to me), then what would be wrong with this kind of strategy: Multiply a string first then eval it:

    perl -MData::Dump -e '$val="(".("{(a,1),(b,2)},"x2).")";@hash{(key1,ke +y2)} = eval $val;dd $val;dd \%hash' "({(a,1),(b,2)},{(a,1),(b,2)},)" { key1 => { a => 1, b => 2 }, key2 => { a => 1, b => 2 } } # Or more concisely: perl -MData::Dump -e '@hash{(key1,key2)} = eval "(".("{(a,1),(b,2)},"x +2).")";dd \%hash'
    At least it seems to do what's required.  I know there's a trailing ',' in $val which could easily be removed, but doesn't seem to be causing a problem with the resulting hash.

      The only way I can see right now to deal with * vis-a-vis glob is to replace it with a character that occurs nowhere else in your data. So maybe (if tybalt89 hasn't already solved this):

      c:\@Work\Perl\monks\tel2>perl -wMstrict -MData::Dump -le "use constant NEVER_PRESENT => qq{\x01}; ;; my $s = 'Prefix5,Prefix6:A,B:*:1,23 value7=10|value88=123'; ;; $s =~ s{ [*] }{${ \NEVER_PRESENT }}xmsg; ;; my ($keyule, $valule) = split ' ', $s, 2; ;; $keyule =~ s{ : }[}:{]xmsg; $keyule = qq[{$keyule}]; print qq{'$keyule'}; $valule =~ s{ [|] }{,}xmsg; $valule = qq[{$valule}]; print qq{'$valule'}; ;; my %hash; for my $v (glob $valule) { my ($vk, $vv) = split '=', $v; for my $k (glob $keyule) { $k =~ s{ ${ \NEVER_PRESENT } }{*}xmsg; $hash{$k}{$vk} = $vv; } } dd \%hash; " '{Prefix5,Prefix6}:{A,B}:{☺}:{1,23}' '{value7=10,value88=123}' { "Prefix5:A:*:1" => { value7 => 10, value88 => 123 }, "Prefix5:A:*:23" => { value7 => 10, value88 => 123 }, "Prefix5:B:*:1" => { value7 => 10, value88 => 123 }, "Prefix5:B:*:23" => { value7 => 10, value88 => 123 }, "Prefix6:A:*:1" => { value7 => 10, value88 => 123 }, "Prefix6:A:*:23" => { value7 => 10, value88 => 123 }, "Prefix6:B:*:1" => { value7 => 10, value88 => 123 }, "Prefix6:B:*:23" => { value7 => 10, value88 => 123 }, }
      Ok, now what's the next phase in the dance-of-the-seven-veils requirement disclosure?

      Update: BTW: I'm still not convinced that glob is the way to go with this application. An algorithmic permuter (update: such as haukex describes) or parser would be more to my liking, but it's your project.


      Give a man a fish:  <%-{-{-{-<

        Nice work, AnomalousMonk.  Thanks for that.

        Why would you prefer replacing the '*' (and reverting it after the 'glob'), over escaping it (which requires no reverting afterwards), e.g.:
        $s =~ s/\*/\\$&/g;

      > If I understand your question correctly, then yes.

      I'm afraid you don't.

      The old approach is fine as long as you only read from the data structure without changing it...

      (The fact that the output of Data::Dump is confusing you doesn't mean it doesn't "work".)

      DB<82> $hash{$_} = $value for @keys; DB<83> x \%hash 0 HASH(0x3598330) 'Prefix1=A:b:1' => HASH(0x35a48e8) 'a' => 1 'b' => 2 'Prefix1=A:b:2' => HASH(0x35a48e8) -> REUSED_ADDRESS 'Prefix1=A:c:1' => HASH(0x35a48e8) -> REUSED_ADDRESS 'Prefix1=A:c:2' => HASH(0x35a48e8) -> REUSED_ADDRESS DB<84> p $hash{'Prefix1=A:b:1'}{a} 1 DB<85> p $hash{'Prefix1=A:b:1'}{b} 2 DB<86> p $hash{'Prefix1=A:c:2'}{b} # reading works! 2 DB<87>

      but once you try to add more data it'll be mirrored, because all values of the outer hash point to the same inner hash.

      (Like a symlinked directory if this helps)

      DB<87> p $hash{'Prefix1=A:c:2'}{X}=42 # new entry 42 DB<88> x \%hash 0 HASH(0x3598330) 'Prefix1=A:b:1' => HASH(0x35a48e8) # appears everywhere 'X' => 42 'a' => 1 'b' => 2 'Prefix1=A:b:2' => HASH(0x35a48e8) -> REUSED_ADDRESS 'Prefix1=A:c:1' => HASH(0x35a48e8) -> REUSED_ADDRESS 'Prefix1=A:c:2' => HASH(0x35a48e8) -> REUSED_ADDRESS DB<89>

      So in case you want to store more data inside the inner hashes, which are supposed to be different, you have to clone the hashes.

      > what would be wrong with this kind of strategy:

      Sorry, I don't have even time to discuss all the traps here.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        Thanks again, LanX.

        "The old approach is fine as long as you only read from the data structure without changing it..."

        OK, good.  I'll just be reading it, so I guess it will work for me.  

        I've just ran this which confirms it should work for me:

        perl -MData::Dump -e '@hash{(key1,key2)} = ({a=>1, b=>2}) x 2;dd \%has +h;print "hash{key1}{a}=$hash{key1}{a}\nhash{key1}{b}=$hash{key1}{b}\n +hash{key2}{a}=$hash{key2}{a}\nhash{key2}{b}=$hash{key2}{b}\n"' do { my $a = { key1 => { a => 1, b => 2 }, key2 => 'fix' }; $a->{key2} = $a->{key1}; $a; } hash{key1}{a}=1 hash{key1}{b}=2 hash{key2}{a}=1 hash{key2}{b}=2
        Thanks again for all your help.