in reply to Re^2: How to assign an array to a value in hash?
in thread Re: How to assign an array to a value in hash?

Yeah , I have some code. I wanted to get like the below one

Ex:-

Key1=value1;

key2=value2,value3,..value10;

key3=value11,value12

I wanted to get like this

key1=value1

key2=value2

key2=value3

key2=value4

key3=value11

key3=value12

After spliting the comma separated values Ex:- value2,value3,valuen not able to insert them into hash.

Some one please kindly help me to insert the splitted values and its key into a hash.

open(DATA1,"<Switcher.properties"); open(DATA2,">FileWrite5.txt") ; while(<DATA1>){ print DATA2 $_; } close(DATA1); close(DATA2); open(DATA1,"<Switcher.properties"); my @Lines=<DATA1>; my %myHash; my @keys; my @y; my @values; my $p=0; my @i; my @x; my $k; foreach my $val (@Lines) { #print "$val"; @i=split('=',$val); $x=0; @keys=@i[x]; @values =@i[$x+1]; print " Keys --> @keys values --> @values \n"; @keys = @i[$x+2]; my $z= @i[$x]; print " The z value--> $z\n"; foreach my $val (@values) { if($val=~m/,/){ @y= split(',',$val); $k=0; foreach my $q (@y){ $myHash{$z}=$q ; print " The value of q --> $q The key for that is --> @i[$x] \n \n "; } print " Key --> @i[$x]\n Multiple values for the key are --> @y "; $k++; } } $x++; $p++; } print " Hash values are as below \n"; while ( my($key,$value)= each %myHash){ print "$key : $value\n " ; }

Replies are listed 'Best First'.
Re^4: How to assign an array to a value in hash?
by AppleFritter (Vicar) on Mar 09, 2015 at 11:03 UTC

    Please, use strict, use warnings, and format/indent your code properly. You'll save yourself a LOT of headaches that way.

    Now, that said, a hash can by its very nature only contain one value for the same key. So simply assigning to the same key more than once won't work, as you'll just overwrite any old value that might previously have been associated with that key.

    However, the value can be a reference to an array (or any data structure, really). perldsc has more information on this, but here's how I might do it:

    #!/usr/bin/perl use strict; use warnings; use feature qw/say/; my %parsed = (); while(<DATA>) { chomp; my ($key, $values) = split "=", $_, 2; my @values = split ",", $values; $parsed{$key} = \@values; } foreach my $key (sort keys %parsed) { say "$key: "; foreach my $value (@{ $parsed{$key} }) { say "\t$value"; } } __DATA__ key1=value1 key2=value2,value3,value4,value4,value5,value6,value7,value8,value9,va +lue10 key3=value11,value12

    This outputs:

    $ perl 1119309.pl key1: value1 key2: value2 value3 value4 value4 value5 value6 value7 value8 value9 value10 key3: value11 value12 $

    The crucial lines here are the following two:

    $parsed{$key} = \@values; # ... foreach my $value (@{ $parsed{$key} }) {

    The first of these takes a reference to @values (using the \ operator); the second takes the reference stored in $parsed{$key} and dereferences it, i.e. converts it back to to an array, by using the @{ ... } circumfix construct. (Since @ is the array sigil, this can mnemonically be thought of as encapsulating a certain something and presenting it as an array on the outside.)

    I hope this'll get you started! If you have further questions, just ask.

      Hi Thanks very much for the hot fix to my problem.

      Actually I need to compare two different versions of the same properties file and than should bring the changes into .csv file.

      Now the question is how I should compare and get the changes of those two hashes of arrays and write it into .csv file.

      Please kindly suggest me the approach.

      Thanks

      Dhananjaya V

        Sure. Here's a script that parses two files and compares the values for each key using List::Compare:

        #!/usr/bin/perl use strict; use warnings; use feature qw/say/; use List::Compare; use List::AllUtils qw/uniq/; sub parse_file($) { my ($filename) = @_; open my $filehandle, "<", $filename or die "Could not open $filename: $!"; my %parsed = (); while(<$filehandle>) { chomp; my ($key, $values) = split "=", $_, 2; my @values = split ",", $values; $parsed{$key} = \@values; } return \%parsed; } my %parsed_file1 = %{ parse_file "File1" }; my %parsed_file2 = %{ parse_file "File2" }; foreach my $key (sort { $a cmp $b } uniq (keys %parsed_file1, keys %pa +rsed_file2)) { my $listcompare = List::Compare->new($parsed_file1{$key} // [] +, $parsed_file2{$key} // []); my @added_values = $listcompare->get_Ronly; my @removed_values = $listcompare->get_Lonly; my @retained_values = $listcompare->get_intersection; say $key; say "\tValues added : ", join ", ", @added_values; say "\tValues removed : ", join ", ", @removed_values; say "\tValues retained: ", join ", ", @retained_values; }

        Here's my File1:

        B23168=AOL,ABC permitted_mac_attempts=1,DEF B23167=Carphone Warehouse TalkTalk,23 B23163=Orange,Red,Blue,Green,White,Black B23970=O2 APPLE=FRITTER

        And my File2:

        B23168=AOL,ABC,DEF,EFG permitted_mac_attempts=1,DEF,34,4 B23167=Carphone Warehouse TalkTalk,23,5,6 B23163=Orange,Red,Blue,Green,Yellow B23970=O2,56 PONY=EARTH

        Using these, the script outputs:

        $ perl 1119397.pl APPLE Values added : Values removed : FRITTER Values retained: B23163 Values added : Yellow Values removed : Black, White Values retained: Blue, Green, Orange, Red B23167 Values added : 5, 6 Values removed : Values retained: 23, Carphone Warehouse TalkTalk B23168 Values added : DEF, EFG Values removed : Values retained: ABC, AOL B23970 Values added : 56 Values removed : Values retained: O2 PONY Values added : EARTH Values removed : Values retained: permitted_mac_attempts Values added : 34, 4 Values removed : Values retained: 1, DEF $

        Writing to a CSV file is left as an exercise for the reader (I don't know how you want your CSV file to look anyway), but I'd strongly suggest using Tux's excellent Text::CSV module.