There's no problem with your for loop, since you are not removing elements from the list over which the for loop iterates. There are two things you could do to achieve the same result in a more perl-ish way. Use a hash to know if an element exists in the @find list, and use grep to turn your input list into another one:
my @in = (1, 2, 3, 4, 3, 5, 3);
my %find = map { $_ => 1 } (3,4);
my @out = grep { !exists $find{$_} } @in;
# or: @out = grep !$find{$_}, @in;
say for @out;
Edit: I meant "two things", not "two thinks", obviously.
Also added the short version of the grep. | [reply] [d/l] |
Hello stevieb,
In the spirit of TMTOWTDI, here’s a variation on Eily’s ++solution that doesn’t require the construction of a hash:
use strict;
use warnings;
use Data::Dump;
use List::MoreUtils 'none';
my @a = (1, 2, 3, 4, 3, 5, 3);
my @find = (3, 4);
dd grep { my $e = $_; none { $e == $_ } @find } @a;
Output:
22:52 >perl 1371_SoPW.pl
(1, 2, 5)
22:52 >
Hope that helps,
| [reply] [d/l] [select] |
my @a = (1, 2, 3, 4, 3, 5, 3);
my @find = (3, 4);
my @out = grep { local $"='q', -1 == index "q@{find}q", "q${_}q" } @a;
have fun :) | [reply] [d/l] |
Challenge accepted :)
First, I went to read perlvar to refresh my memory on what the $" special variable is (list separator), so I was able to weasel the code down to this:
my @out = grep { -1 == index " @{find} ", " ${_} " } @a;
Already knowing that grep works 'backwards', I then followed that up with a peruse of perldoc -f index, and found out that the order of args are STRING, SUBSTR and POSITION. In this case, we're not using POSITION, as $_ is the value of the current array element, and is the SUBSTR to index().
So after I realized that "q@{find}q" was simply flattening the @find array into a string of its values separated by a different separator (which I changed back to the default whitespace), I was able to simplify a bit further:
my @out = grep { -1 == index " @find ", $_} @a;
Because although there are spaces around each element in the string-ified list, the whitespace regarding the SUBSTR is irrelevant, because index() is simply checking whether SUBSTR is in STRING, not checking for an exact match.
Because if this, I figured I could chop off two more chars:
my @out = grep { -1 == index "@find", $_} @a;
Lastly, in the previously mentioned perldoc -f index, it states that if the SUBSTR is not found in STRING, it'll return -1. In the last operation of the grep, you check to see if the return from index() is equal to -1, and if true (ie., the substr isn't found in the string-ified @find array), you push it onto the @out array, because grep does so when the block returns a true value. So you convert the expression to a true value after you've found that the original array doesn't match anything in the @find array.
Am I close? ;)
-stevieb | [reply] [d/l] [select] |
my @a = (1, 2, 3, 4, 3, 5, 3, 34);
my @find = (4, 3, 53);
my @out = grep { -1 == index "@find", $_ } @a;
:) | [reply] [d/l] |