Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Array lookup

by bartrad (Beadle)
on Apr 16, 2018 at 20:40 UTC ( #1213023=perlquestion: print w/replies, xml ) Need Help??

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

Hi all, I'm trying to create a new array called @result that contains the elements of @dead_list without those that also appear in @get_list.

@dead_list

$VAR1 = [ [ 100, 101, 103, 200, 201, 202, 203, 210, 211, 212, 220, 221, 222, 230, 231, 232, 233, 240, 241, 242, 243, 1000, 1001, 1002, 1010, 1011, 1012, 1020, 1021, 1022, 1120, 1121, 1122, 1210, 1211, 1212 ] ];

@get_list

$VAR1 = [ [ '100', '200', '210', '220', '230', '240', '1000', '1001', '1002', '1120', '1210' ] ];

Here's the code I'm using:

sub remove_x99 { my @dead_list = shift; my @get_list = shift; ###REMOVE TARGET X99 ENTRIES FROM DEAD_lIST print Dumper\@dead_list; print Dumper\@get_list; my %lookup; my @result; @lookup{@get_list} = (); print Dumper \%lookup; foreach my $elem (@dead_list) { push(@result, $elem) unless exists $lookup{$elem}; } print Dumper\@result; }

And here's what the Dumper of %lookup looks like:

$VAR1 = { 'ARRAY(0x1a56440)' => undef };

I'm completely baffled as @results just returns the exact same thing as @dead_list... can anyone help please?

Replies are listed 'Best First'.
Re: Array lookup
by SuicideJunkie (Vicar) on Apr 16, 2018 at 20:56 UTC

    Well, as you saw in the dumper, your hash contains ARRAY(0x1a56440) and only ARRAY(0x1a56440). That's the stringification of the address of your array. (Which also points to where the problem is happening.)

    You then push all the elements of your list unless the element is 'ARRAY(0x1a56440)'. Which is all the elements.

    When you push all the elements on, of course your arrays will have the same contents. :)

    Check how you're passing those arrays in, and make sure you dereference the arrayrefs getting passed in, to avoid assigning a single value (the arrayref) into a new array of one element.

Re: Array lookup
by 1nickt (Abbot) on Apr 17, 2018 at 00:48 UTC

    Another problem you have is in how you are passing your arguments to your subroutine.

    $ perl -Mstrict -wE 'sub say_args { my @foo = shift; my @bar = shift; +say "foo: $_" for @foo; say "bar: $_" for @bar; } my @foo = qw/a b c/ +; my @bar = qw/x y z/; say_args( @foo, @bar );' foo: a bar: b $ perl -Mstrict -wE 'sub say_args { my @foo = shift; my @bar = shift; +say "foo: $_" for @foo; say "bar: $_" for @bar; } my @foo = qw/a b c/ +; my @bar = qw/x y z/; say_args( \@foo, \@bar );' foo: ARRAY(0x17b85e8) bar: ARRAY(0x17b9110) $ perl -Mstrict -wE 'sub say_args { my $foo = shift; my $bar = shift; +say "foo: $_" for @$foo; say "bar: $_" for @$bar; } my @foo = qw/a b +c/; my @bar = qw/x y z/; say_args( \@foo, \@bar );' foo: a foo: b foo: c bar: x bar: y bar: z
    As you can see you need to pass references to your arrays (else they will be concatenated, and additionally you will only get one element at a time with shift), and then dereference them inside the subroutine. See perlreftut.

    Hope this helps!


    The way forward always starts with a minimal test.
Re: Array lookup
by Laurent_R (Canon) on Apr 17, 2018 at 06:31 UTC
    If you pass two arrays (or two lists) to a subroutine, they will be flattened into a single array contained in @_.

    You need to pass array references when calling the szubroutine, something like this:

    remove_x99(\@dead_list, \@get_list);
    Then, within the subroutine, you can either access directly the elements refered to by the array refs:
    sub remove_x99 { my $dead_list_ref = shift; my $get_list_ref = shift; my %lookup = map {$_ => 1} @$get_lisr_ref; # ...
    or, if you find it clearer, start by unpacking the arguments:
    sub remove_x99 { my $dead_ref = shift; my @dead-list = @$dead-ref; #...

    Update: there are two typos on the last code line above (due to my clumsiness on the small keyboard of my mobile device on which I typed this message and to the fact that my train was arriving at my place of arrival and I therefore did not take enough time to review what I had written). The last line should be:

    my @dead_list = @$dead_ref;

      BTW, my @dead-list = @$dead-ref; will result in something like Global symbol "$dead" requires explicit package name (did you forget to declare "my $dead"?).

      Remember The Syntax of Variable Names.

      Best regards, Karl AKA Dr Wisenheimer

      «The Crux of the Biscuit is the Apostrophe»

      perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

        Thanks. I updated the post with a correction (but did not change the code itself to avoid making your post look strange). I am just a bit clumsy on the keyboard of my mobile device.
Re: Array lookup
by Marshall (Canon) on Apr 17, 2018 at 17:15 UTC
    Your dumper output looked odd to me. Basically you have one row of what would be an Array of Array (AoA). That would have happened if say you initialized these two arrays with square brackets instead of paren's. I'm not sure if that is what you really wanted?

    I demo that below and changed to a more usual initialization of a 1D array..

    #!usr/bin/perl use strict; use warnings; use Data::Dumper; my @x = [100, 101]; #may not be what you want? print Dumper \@x; my @dead_list = (100, 101, 103, 200, 201, 202, 203, 210, 211, 212, 220, 221, 222, 230, 231, 232, 233, 240, 241, 242, 243, 1000, 1001, 1002, 1010, 1011, 1012, 1020, 1021, 1022, 1120, 1121, 1122, 1210, 1211, 1212); my @get_list = ( '100', '200', '210', '220', '230', '240', '1000', '1001', '1002', '1120', '1210',); sub remove_x99 { my ($deadlist_ref, $getlist_ref) = @_; my %lookup = map{$_=>1}@$getlist_ref; my @result = grep{!exists $lookup{$_}}@$deadlist_ref; return @result; } my @result = remove_x99 (\@dead_list, \@get_list); print "@result\n"; __END__ $VAR1 = [ [ 100, 101 ] ]; 101 103 201 202 203 211 212 221 222 231 232 233 241 242 243 1010 1011 +1012 1020 1021 1022 1121 1122 1211 1212 Note: in the sub if you wanted to modify dead_list: @$deadlist_ref = grep{!exists $lookup{$_}}@$deadlist_ref; would do that.
Re: Array lookup
by dorko (Prior) on Apr 17, 2018 at 18:03 UTC
    If you don't care how you get the results, then this works (if I read your problem statement correctly). It uses List::Compare from CPAN.
    #!usr/bin/perl use strict; use warnings; use feature 'say'; use Data::Dumper::Simple; use List::Compare; my @dead_list = (100, 101, 103, 200, 201, 202, 203, 210, 211, 212, 220, 221, 222, 230, 231, 232, 233, 240, 241, 242, 243, 1000, 1001, 1002, 1010, 1011, 1012, 1020, 1021, 1022, 1120, 1121, 1122, 1210, 1211, 1212); my @get_list = ( '100', '200', '210', '220', '230', '240', '1000', '1001', '1002', '1120', '1210',); my $lc = List::Compare->new(\@dead_list, \@get_list); my @result = $lc->get_unique; say Dumper(@result); __END__ @result = ( '101', '1010', '1011', '1012', '1020', '1021', '1022', '103', '1121', '1122', '1211', '1212', '201', '202', '203', '211', '212', '221', '222', '231', '232', '233', '241', '242', '243' );

    Cheers,

    Brent

    -- Yeah, I'm a Delt.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (1)
As of 2020-10-25 06:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My favourite web site is:












    Results (249 votes). Check out past polls.

    Notices?