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?
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.
| [reply] |
Re: Array lookup
by 1nickt (Canon) on Apr 17, 2018 at 00:48 UTC
|
$ 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.
| [reply] [d/l] [select] |
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;
| [reply] [d/l] [select] |
|
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
| [reply] [d/l] [select] |
|
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.
| [reply] |
|
Re: Array lookup
by Marshall (Canon) on Apr 17, 2018 at 17:15 UTC
|
#!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.
| [reply] [d/l] |
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
| [reply] [d/l] |
|
|