in reply to Hash Multiple values for a key-Filtering unique values for a key in hash

One more thing here, Let's say I get key/values as below in my hash

Where a certain value appears twice for different keys, for e.g. 'Eufaula' is a value for key 'Alabama' & 'California'

Likewise, 'Beacon' appears for both 'New York' & 'Utah'

Can i delete this for one key only (no particular where i need to retain this value for which key, just need once in any key)

my $HASH1 = { 'Alabama' => ['Andalusia', 'Anniston', 'Clanton', 'Eufaula', 'Aubur +n'], 'California' => ['Barstow','Eufaula'], 'New York' => ['Amsterdam','Coney Island','Beacon'], 'Utah' => ['Beacon','Layton'] };

so my result hash should look like

my $HASH1 = { 'Alabama' => ['Andalusia', 'Anniston', 'Clanton', 'Eufaula', 'Aubur +n'], 'California' => ['Barstow'], 'New York' => ['Amsterdam','Coney Island','Beacon'], 'Utah' => ['Layton'] };
Thanks.

Replies are listed 'Best First'.
Re^2: Hash Multiple values for a key-Filtering unique values for a key in hash
by tobyink (Canon) on May 23, 2017 at 10:36 UTC

    You could solve both problems in one go by temporarily inverting your hash. So instead of a (state => cities) hash, you have a (city => state) hash. Then you can invert it back.

    use strict; use warnings; use Data::Dumper; my %hash = ( 'Alabama' => ['Andalusia','Anniston','Clanton','Eufaula','Auburn' +,'Auburn','Auburn','Auburn'], 'California' => ['Barstow','Eufaula'], 'New York' => ['Amsterdam','Coney Island','Beacon','Beacon','Beaco +n','Beacon','Beacon'], 'Utah' => ['Beacon','Layton'], ); # Invert the hash. my %inverted = map { my $state = $_; map { $_ => $state } @{$hash{$state}} } sort keys %hash; print Dumper \%inverted; # And back again: %hash = (); while (my ($city, $state) = each %inverted) { push @{ $hash{$state} ||= [] }, $city; } print Dumper \%hash;
Re^2: Hash Multiple values for a key-Filtering unique values for a key in hash
by hippo (Archbishop) on May 23, 2017 at 08:55 UTC
    Can i delete this for one key only

    Of course. Simply amend your algorithm to maintain a separate list (which could be a hash for easy/fast lookups) of deleted values. Never delete a value which is already in that list.

Re^2: Hash Multiple values for a key-Filtering unique values for a key in hash
by kcott (Archbishop) on May 24, 2017 at 05:44 UTC
    "Can i delete this for one key only (no particular where i need to retain this value for which key, just need once in any key)"

    I made reference to that in my original reply:

    "To keep the values unique for a specific key, without removing duplicates from the values of other keys, you'll need to clear the %seen hash for each arrayref value."

    In this code:

    for (values %$HASH1) { my %seen; $_ = [ grep { ! $seen{$_}++ } @$_ ]; }

    Just move the "my %seen;" line out of the loop:

    my %seen; for (values %$HASH1) { $_ = [ grep { ! $seen{$_}++ } @$_ ]; }

    Which, as the loop now only contains one statement, you can write more succinctly as:

    my %seen; $_ = [ grep { ! $seen{$_}++ } @$_ ] for values %$HASH1;

    I put that into the original code I gave you (along with your new HoA). Here's the output:

    { "Alabama" => ["Andalusia", "Anniston", "Clanton", "Eufaula", "Aub +urn"], "California" => ["Barstow"], "New York" => ["Amsterdam", "Coney Island", "Beacon"], "Utah" => ["Layton"], }

    Which exactly matches what you have for "so my result hash should look like".

    By the way, purely for academic interest, because I can't see that it gains you anything in this particular instance, if you're using Perl 5.10, or later, you could have reduced those two lines to this one:

    $_ = [ grep { state %seen; ! $seen{$_}++ } @$_ ] for values %$HASH1;

    I tested that: the output is identical. See state for more details.

    — Ken