http://www.perlmonks.org?node_id=1222553


in reply to Re: assigning arrays as values to keys of hash
in thread assigning arrays as values to keys of hash

I specifically need a hash of arrays.. any way that's possible?
  • Comment on Re^2: assigning arrays as values to keys of hash

Replies are listed 'Best First'.
Re^3: assigning arrays as values to keys of hash
by kevbot (Vicar) on Sep 18, 2018 at 05:20 UTC

    Why do you need a hash of arrays? Is this question related to homework? As mentioned by jwkrahn, using a multi-level hash would allow you to readily avoid duplicates.

    I have the current code that works but it doesn't get rid of the duplicates

    The code you posted does not seem to work. When I ran your code, the hash keys contained an entire line of text and the values were undefined array references. When I removed the double quotes from the first argument to split, I was able to get a hash of array references. However, as you mentioned, there are duplicates in the array references.
    #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my $file = 'file.txt'; open( FILE, '<', $file ) or die $!; my %hash; while ( <FILE> ) { chomp; my $lines = $_; my $key = (split(/ /, $lines))[0]; my $value = (split(/ /, $lines))[1]; push @{ $hash{$key} }, $value; } print Dumper(\%hash); exit;

    There are quite a few ways you could go about removing the duplicates. Here is one way to do it with help from the uniq function of List::Util.

    #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; use List::Util qw/uniq/; my $file = 'file.txt'; open( FILE, '<', $file ) or die $!; my %hash; while ( <FILE> ) { chomp; my $lines = $_; my ($key, $value) = split(/ /, $lines); push @{ $hash{$key} }, $value; } foreach my $key( keys %hash ){ my @array = @{$hash{$key}}; my @uniq_elems = uniq @array; $hash{$key} = \@uniq_elems; } print Dumper(\%hash); exit;
Re^3: assigning arrays as values to keys of hash
by AnomalousMonk (Archbishop) on Sep 18, 2018 at 06:01 UTC

    push-ing each "organ" to an autovivified anonymous array keyed by its "animal" allows preservation of the original order of "organs" as found in the file (if this is of any importance). If preserving original order isn't important, use the simpler two-level hash approach described by others.

    c:\@Work\Perl\monks>perl -wMstrict -le "use autodie; no autodie qw(open close); ;; use List::MoreUtils qw(uniq); ;; use Data::Dump qw(dd); ;; my $file = qq{bird beak\n} . qq{bird beak\n} . qq{bird claw\n} . qq{bird wings\n} . qq{bird feathers\n} . qq{snake fangs\n} . qq{snake scales\n} . qq{snake fangs\n} . qq{snake tail\n} ; print qq{[[$file]]}; ;; open my $fh, '<', \$file or die qq{opening ram file: $!}; ;; my %hash; while (my $line = <$fh>) { my $parsed = my ($animal, $organ) = $line =~ m{ \A ([[:alpha:]]+) \s+ ([[:alpha:]]+) \Z }xmsg; ;; die qq{bad line '$line'} unless $parsed; ;; push @{ $hash{$animal} }, $organ; } ;; close $fh or die qq{closing ram file: $!}; ;; @$_ = uniq @$_ for values %hash; dd \%hash; " [[bird beak bird beak bird claw bird wings bird feathers snake fangs snake scales snake fangs snake tail ]] { bird => ["beak", "claw", "wings", "feathers"], snake => ["fangs", "scales", "tail"], }


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

Re^3: assigning arrays as values to keys of hash
by jwkrahn (Abbot) on Sep 18, 2018 at 05:23 UTC
    my %unique; while ( <FILE> ) { my ( $key, $value ) = split; $hash{ $key }{ $value } = (); } $_ = [ keys %$_ ] for values %hash; print Dumper \%hash;