Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Unique list of hashes

by mrguy123 (Hermit)
on Mar 02, 2015 at 11:12 UTC ( [id://1118393]=perlquestion: print w/replies, xml ) Need Help??

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

Hi monks
Haven't asked a question in a while but this is an interesting case (also I really need to solve it).
Say I have a list of hashes, for example:
@students = ( { name => "Guy", college => "Yale", }, { name => "Gil", college => "Harvard", }, { name => "Gil", college => "Harvard", }, );
I want to make this list unique, meaning it needs to look like this:
@uniq_students = ( { name => "Guy", college => "Yale", }, { name => "Gil", college => "Harvard", }, );
List::MoreUtils::uniq doesn't work on lists of hashes so that's a no go. I can do it for one hash key (below) but for 2 or more keys it's tricky
##Solution for one hash key my @unique = do { my %seen; grep { !$seen{$_->{name}}++ } @students};
Of course I can find a workaround (e.g. make each hash into a string and then sort ...) but I would like to try and find something better (and shorter) if possible
Any ideas?



Everybody seems to think I'm lazy
I don't mind, I think they're crazy

Replies are listed 'Best First'.
Re: Unique list of hashes
by hdb (Monsignor) on Mar 02, 2015 at 11:29 UTC

    Like this?

    use strict; use warnings; use Data::Dumper; my @students = ( { name => "Gil", college => "Yale", }, { name => "Gil", college => "Harvard", }, { name => "Gil", college => "Harvard", }, ); my @unique = do { my( %seenName, %seenCollege ); grep { !$seenName{$_->{name}}++ or !$seenCollege{$_->{college}}++ +} @students}; print Dumper \@unique;

    UPDATE: Sorry, got that wrong. It should be:

    my @unique = do { my %seen; grep { !$seen{$_->{name}}{$_->{college}}++ } @students};
      Nice!!
      I was actually thinking along the line of your first solution, but couldn't get figure out how to take care of the "or". I think this is just what I need.
      Thanks!
Re: Unique list of hashes
by LanX (Saint) on Mar 02, 2015 at 11:37 UTC
    As a side note: I suggest you better try to find a unique identifier for each student and restructure your data:

    %students = ( 1111 => { name => "Guy", college => "Yale", }, 2222 => { name => "Gil", college => "Harvard", }, );

    Keep in mind that equally named persons are not that rare, even in the same university.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)

    PS: Je suis Charlie!

Re: Unique list of hashes
by parv (Parson) on Mar 02, 2015 at 11:41 UTC

    Make a key out of combined values to search for uniqueness ...

    @uniq = grep !$seen{ join '' , sort values %{ $_ } }++ , @list ;
      Make a key out of combined values to search for uniqueness ... @uniq = grep !$seen{ join '' , sort values %{ $_ } }++, @list;

      So these are all the same?

      my @list = ( { foo=>'bar', quz=>'baz' }, { abc=>'bar', def=>'baz' }, { ijk=>'ba', xyz=>'rbaz' }, { r=>'ba', s=>'rba', t=>'z' }, { x=>'barbaz' }, );

        Using a delimiter that cannot appear in the values would be useful... like a pipe or such.

        Nope, not all are same as you already know. hdb has already given slightly complicated method to satisfy your situation.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1118393]
Approved by hdb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (3)
As of 2024-04-19 17:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found