Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

list item comparison

by robertw (Sexton)
on Jul 12, 2012 at 21:37 UTC ( [id://981507]=perlquestion: print w/replies, xml ) Need Help??

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

Hey guys, I have a list of a lot of numbers, and i want to put that list into a subroutine which checks if any item of the list is equal to any other and then says which item is equal to the other list item if it is in there, would you know how such a subroutine would look like? Thank you so much in advance

Replies are listed 'Best First'.
Re: list item comparison
by davido (Cardinal) on Jul 12, 2012 at 22:44 UTC

    This subroutine accepts a list of numbers, and returns a list of hashrefs that look like: { $number => [ $idx1, $idx2, $idx_n, ... ] }, where each index represents where that particular number will be found in the original list.

    use strict; use warnings; use Data::Dump 'dump'; my @numbers = ( 1, 2, 2, 4, 8, 42, 7, 2, 6, 7, 9, 42 ); my @duplicate_locations = find_duplicates( @numbers ); dump @duplicate_locations; sub find_duplicates { my @list = @_; my $idx; my %buckets; foreach my $item ( @list ) { push @{$buckets{$item}}, $idx++; } my @rv; foreach my $key ( keys %buckets ) { push @rv, { $list[$buckets{$key}->[0]] => $buckets{$key} } if @{$buckets{$key}} > 1; } return @rv; }

    The output...

    ({ 42 => [5, 11] }, { 7 => [6, 9] }, { 2 => [1, 2, 7] })

    Update:Simplifying the data structure returned simplifies the subroutine that produces it:

    use strict; use warnings; use Data::Dump 'dump'; my @numbers = ( 1, 2, 2, 4, 8, 42, 7, 2, 6, 7, 9, 42 ); dump { find_duplicates( @numbers ) }; sub find_duplicates { my @list = @_; my $idx; my %buckets; foreach my $item ( @list ) { push @{$buckets{$item}}, $idx++; } delete @buckets{ grep { @{$buckets{$_}} < 2 } keys %buckets }; return %buckets; }

    Now the output is...

    { 2 => [1, 2, 7], 7 => [6, 9], 42 => [5, 11] }

    ...so the actual return value from the sub is a hash where the keys are the values from your original list, and the values are array refs containing lists of where the corresponding elements are found. ...and we've stripped away any that weren't duplicated.


    Dave

      Thanks a lot you guys thats great coding, I will definately not need more than this, what i had so far was this, but your scripts definately beat it, although i made it if this is unequal put it in this list just to get more understanding of what i had to do.

      foreach @allcards { if $allcards[$count] != @userinput[0] or if $allcards[$count] != @userinput[1] or if $allcards[$count] != @userinput[2] or if $allcards[$count] != @userinput[3] or if $allcards[$count] != @userinput[4] or if $allcards[$count] != @userinput[5] { push (@resthand,$allcards[$count]); } count++;}
Re: list item comparison
by dasgar (Priest) on Jul 12, 2012 at 21:58 UTC

    Where's your code that you have tried?

    I'll be nice share some code that should get you started. I'll leave it to you to figure out how to bundle it in a subroutine, how to pass data into and out of it, and any other modifications you need to meet your needs.

    use strict; use warnings; my (@list) = (1,1,2,3,4,4,4,5,6,7,7,8,9,10); my %check; foreach my $item (@list) { if (exists $check{$item}) {$check{$item}++;} else {$check{$item} = 1;} } foreach my $key (keys %check) { my $count = $check{$key}; if ($count > 1) { print "$key was in the list $count times.\n"; } }

      There is no need to check if the $item exists in the hash. When you increment a the value for a key which doesn't exist, the key springs into existence. So lines 8-11 can be replaced by:

      $check{$_}++ for @list;
        When you increment a the value for a key which doesn't exist, the key springs into existence.

        Didn't know that. Thanks for the info.

        However, I'd like to point out one thing. Back when I was first learning Perl, your one line for loop code would have had me thoroughly confused. Based on the original question asked by the OP, I was left with the impression that the OP was a bit of a beginner. In that case, my foreach loop would probably be somewhat easier to follow along and understand.

        Plus, I personally find that my foreach loop more closely matches how I would think through the task, which in turn would mean easier code for me to personally maintain. Just a personal preference.

        Anyways, thanks for the tip!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-24 23:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found