The bug in your script seems to stem from a misunderstanding of what happens when you evaluate an array in Boolean context. if(@array) {... doesn't test every single element against some implicit variable such as $_. All it does, is evaluate the array in scalar context, which returns the number of elements in the array. Therefore, if there are zero elements, the conditional will be false. If there are more than zero elements, it will be true.
Here are a couple of ways to do it. In terms of computational complexity, this first one is a linear growth-rate solution:
my $count = do { my %seen; @seen{@somenames} = (); my $c; foreach my $name ( @allnames ) { $c++ if exists $seen{$name}; } $c; };
This is a quadratic solution:
my $count; foreach my $name (@allnames) { $count++ if grep { $_ eq $name } @somenames; }
The first solution trades memory for computational efficiency; its rate of growth in memory requirements is linear, tied to the growth of @somenames. Its rate of growth in computational complexity is tied to the growth of @allnames+@somenames. Update: I've limited the duration of the memory requirement to a narrow scope; in theory Perl could reuse the memory consumed by %seen since it's falling out of scope at the end of the do{} block.
The second solution has constant memory requirements, but must run through "@somenames" one time for every element in @allnames. This could become very slow very fast, if the arrays grow. The second solution could, in principle, be improved upon by using List::Util::any. Unfortunately (or fortunately, depending on how you look at it), grep is highly optimized in ways that seem to be unavailable to XSUBS, so 'any' it often not a performance win, though its semantic purity may still make it a good alternative.
Dave
In reply to Re: check all elements of an array against another array...
by davido
in thread check all elements of an array against another array...
by tjo7777
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |