Re: iterating through array and saving matches to new array
by poj (Abbot) on Apr 15, 2018 at 06:40 UTC
|
#!/usr/bin/perl
use strict;
use Data::Dump 'pp';
my @a = 1..1000;
my @newa = grep( $_>850,@a );
pp \@newa;
poj | [reply] [d/l] |
Re: iterating through array and saving matches to new array
by Marshall (Canon) on Apr 15, 2018 at 13:28 UTC
|
Probably what you wanted is "my @newa;" instead of "our @newa;". "our" is a special thing usually seen in a module. Read perl doc our for more info. In a module, a my variable cannot be exported, but an our variable can be.
Yes, grep is the right tool here. I personally prefer the block form of grep and map.
my @a = 1..1000;
my @newa = grep{$_>850}@a;
Grep is a "filter" operation. | [reply] [d/l] |
Re: iterating through array and saving matches to new array
by karlgoethebier (Abbot) on Apr 15, 2018 at 18:33 UTC
|
#!/usr/bin/env perl
use strict;
use warnings;
use Iterator::Simple qw(iter igrep list);
use Data::Dump;
dd list ( igrep { $_ > 850 } iter([1..1000]));
__END__
Please see also Iterator::Simple.
Best regards, Karl
«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] |
Re: iterating through array and saving matches to new array
by learnedbyerror (Monk) on Apr 15, 2018 at 18:18 UTC
|
With the replacement of our with my, your method, as a generalized method is fine.
poj's use of grep is preferred when you have a simple criterion, such as your >850, as it will be faster than the generalized method.
| [reply] [d/l] [select] |
|
I am not sure about that!
That idea of "faster" is true in Python's equivalent, but I'm not at all sure about that in Perl.
In Perl, the foreach loop should run at about the same speed.
| [reply] |
Re: iterating through array and saving matches to new array
by pwagyi (Monk) on Apr 16, 2018 at 07:15 UTC
|
As other monks had pointed out, use lexical scope (my over our).
and grep is definitely suitable here.
I'm not exactly sure why you need even grep/filtering if you want to find numbers between 850 and 1000?
You could as well use.
my $lower_bound = 850;
my $upper_bound = 1000;
my @newa = ($lower_bound+1 .. $upper_bound);
| [reply] [d/l] |
Re: iterating through array and saving matches to new array
by jazzfan (Novice) on Apr 15, 2018 at 20:05 UTC
|
Thanks POJ, et al. Let me abstract the problem to be sure I understand it: If I want to save matches to new array, and make it visible outside the foreach (or while, if, etc) then you are proposing not creating the block in the first place, and in cases where you have to use a code block, and return the new array, just use "my" and not "our" appears to be the take away.
| [reply] |
|
... where you have to use a code block, and return the new array, just use "my" and not "our" appears to be the take away.
The preference of a lexical (my) variable over a package-global (our) variable has nothing to do with accessing a value generated within a code block (or lexical scope, as I would express it). The code in the OP using a package-global to return the values produced in the for-loop scope works just fine as far as it goes. The problem is that you are then left with a global variable. As the old punchline goes, now you've got two problems.
Global variables are officially Frowned Upon because they are... well, global: they can be accessed from anywhere in your program and can be the source of "spooky action at a distance" problems, potentially very tricky to debug. Lexical variables have a well-defined and potentially extremely limited scope (the more limited, the better), and can (usually) be reasoned about and debugged more easily. Don't give yourself headaches.
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
Re: iterating through array and saving matches to new array
by jazzfan (Novice) on Apr 15, 2018 at 21:07 UTC
|
my @b = 1..1000;
my @c = 900..1000;
my @d = 910..1000;
my @newb = grep {$_>850}(@b&&@c&&@d);
| [reply] [d/l] |
|
&& imposes scalar boolean context on the first argument. Therefore, the grep on line 4 iterates over @d only provided @b and @c aren't empty. To iterate over several arrays, use comma:
my @newb = grep $_ > 850, @b, @c, @d;
It's also a good idea to test the code before posting here ;-)
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [d/l] [select] |
|
c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le
"my @b = (1, 2, 3, 11, 12, 13);
my @c = (4, 5, 6, 14, 15, 16);
my @d = (7, 8, 9, 17, 18, 19);
my @newb = grep { $_ > 10 } (@b && @c && @d);
dd \@newb;
"
[17, 18, 19]
Something seems to have happened to the contents of the @b and @c arrays. Again, did you intend this? This result comes from the short-circuiting behavior of the && || and or logical operators; see perlop. (Please see the non-core module Data::Dump for the dd() function. The core Data::Dumper module has dumper functions that you will not need to install a module to access.)
Update: Changed the array initializations in the example code above to make the point more clearly.
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
To make the the "or" of all 3 arrays with unique values > 850, consider this:
#!/usr/bin/perl
use strict;
use warnings;
my @b = 1..1000;
my @c = 900..1000;
my @d = 910..1000;
# my @newb = grep {$_>850}(@b&&@c&&@d); ### will not work!
my %seen;
my @newb = map{ ($_ > 850 and !$seen{$_}++) ? $_: ()} (@b,@c,@d);
print "@newb\n";
I am not sure what the intent here is. | [reply] [d/l] |
|
Wouldn't the code be more readable/maintainable/etc with List::Util::uniq():
my @newb = uniq grep $_ > 850, @b, @c, @d;
Results are the same per Test::More::is_deeply(). (In older Perls, see List::MoreUtils::uniq.)
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
|
|
Re: iterating through array and saving matches to new array
by jazzfan (Novice) on Apr 16, 2018 at 21:07 UTC
|
No that was not what I meant by "working" - I posted my last comment too hastily, without sufficient testing.
| [reply] |