Re: Finding Redundant values in arrays
by tomhukins (Curate) on Jun 08, 2001 at 00:03 UTC
|
| [reply] |
Re: Finding Redundant values in arrays
by bikeNomad (Priest) on Jun 07, 2001 at 23:59 UTC
|
You can count occurrences using a hash: @test = ("camel","alpaca","penguin","alpaca","monkey","camel","camel")
+;
my %counts;
$counts{$_}++ foreach @test;
@redundant = grep { $counts{$_}>1 } keys(%counts);
And please note that camels are never redundant <g>.
update: changed map to foreach so as to avoid the dreaded map in void context | [reply] [d/l] |
|
|
$counts{$_}++ for @test;
or (for us antediluvian 5.004 types)
for (@test) {$counts{$_}++}
I was hoping there was a Schwartzian Transform analog for this, just for the fun of running the whole thing into one line, but I can't come up with one.
Update:
No sooner posted than obsolete...
@redundant = grep {++$counts{$_} > 1} @test;
Oops!
@redundant = grep {++$counts{$_}==2} @test;
and a pox on foolish monks who post without full testing...
If God had meant us to fly, he would *never* have give us the railroads.
--Michael Flanders | [reply] [d/l] [select] |
Re: Finding Redundant values in arrays
by dvergin (Monsignor) on Jun 08, 2001 at 00:03 UTC
|
my @test = qw(camel aplaca peguin aplaca
monkey camel camel);
my %temp;
my @redundant = grep $temp{$_}++ == 1, @test;
print "@redundant\n";
Update: Good catch, Wog. It works as
expected now. I've corrected the line
from:
#my @redundant = grep $temp{$_}++, @test;
I did test but didn't see
the typo in converting to a qw(). Typing like 60 and
missed the curve!
Weak rejoinder: though
not the spec for this problem, it would
be useful in some circumstances. ;-) | [reply] [d/l] [select] |
|
|
Although this code works as given it is not a working
solution. If we remove the " from the
'camel"', then it prints camel twice.
(And it would do it more times if there were a fourth camel
in the array, etc.)
| [reply] [d/l] [select] |
Re: Finding Redundant values in arrays
by IraTarball (Monk) on Jun 08, 2001 at 00:18 UTC
|
This is spun off of the Extracting Unique Elements from a List section of the Perl Cookbook.
%seen = ();
@unique = grep { ++$seen{$_} == 2} @test;
If you're not familiar with grep you can read all about it in perldoc -f grep but as I understand it, it returns a list consisting only of the elements in @test for which the block or expression return true. So for this snippet the block { ++$seen{$_} == 2} only returns true the second time the element has been seen.
Hope this helps
Ira
"So... What do all these little arrows mean?"
~unknown | [reply] [d/l] [select] |
(zdog) Re: Finding Redundant values in arrays
by zdog (Priest) on Jun 08, 2001 at 00:01 UTC
|
Updated with info from below, but still an incorrect answer:
for my $test (@test)
{
push (@redundant, $test) unless grep { $test eq $_ } @redundant;
}
Zenon Zabinski | zdog | zdog7@hotmail.com
| [reply] [d/l] |
|
|
Oops! You are mistaken...
my @test = qw(camel aplaca peguin aplaca
monkey camel camel");
my @redundant;
for (@test) {
next if grep ("$_", @redundant);
push (@redundant, $_);
}
print "@redundant\n";
Prints: camel
Update: zdog asked about this
in a private CB message
so here goes. tomhukins is not quite correct in his
description of the problem. What happens is this:
grep ("$_", @redundant) in a scalar context
returns the number of times the expression $_ is true
for all the elements of @redundant. But the first
time through, there are no elements in @redundant so $_
is evaluated zero times.
So the first time through the loop, the "next if"
fails and "camel" is pushed onto @redundant. Each time
through the loop after than, @redundant does
contain an element and the grep in a scalar context returns
1 meaning "for the one element in @redundant, $_
(the element 'camel') is true."
(Note: I am aware of the discussion about
whether to say that grep always returns a list but that
a list in scalar context evaluates to the number of elements
or whether to say that grep in a scalar context returns
a number. perlfunc says: "In scalar context,
[grep]
returns the number of times the expression was true.") | [reply] [d/l] [select] |
|
|
This is broken, notice that it just prints the first element of the @test array? So aplaca doesn't print. In fact if you put peguin as the first element of test it prints peguin. The problem is that you're trying to be to terse. The $_ that you're using in the grep is not the $_ that aliases an element of @test, it's the $_ that aliases an element of @redundant (grep uses $_ too). So you're saying next if there's an element of redundant that matches an element of redundant. Probably not really what your were thinking of.
Update: Well, it was broken. I started getting down votes for this node, I guess 'cause it's no longer applicable. :)
Ira
"So... What do all these little arrows mean?"
~unknown
| [reply] [d/l] [select] |
|
|
This won't work. The for (@test) line iterates
through each element of @test, but then you
skip each element with the grep you're using.
In English you're saying: for each element in the array,
only keep that element if it is not in the array.
Also, there is no need to place quotes round $_.
Update: This is wrong. dvergin explains
what really happens in Re: (zdog) Re: Finding Redundant values in arrays.
| [reply] [d/l] [select] |
Re: Finding Redundant values in arrays
by wog (Curate) on Jun 08, 2001 at 00:02 UTC
|
my @test =
qw( camel aplaca peguin aplaca monkey camel camel );
my %test;
$test{$_}++ for @test;
my @redundant;
while (my($k,$v) = each %test) {
push @redundant, $k if $v > 1;
}
print "@redundant\n";
| [reply] [d/l] |
Re: Finding Redundant values in arrays
by tachyon (Chancellor) on Jun 08, 2001 at 00:08 UTC
|
my @test = ("camel","aplaca","peguin","aplaca","monkey","camel","camel
+");
my (%duplicate,%test,@redundant);
for (@test) {
$duplicate{$_} = 1 if defined $test{$_};
$test{$_} = 1;
}
@redundant = keys %duplicate;
print "@redundant\n";
| [reply] [d/l] |
Re: Finding Redundant values in arrays
by tachyon (Chancellor) on Jun 08, 2001 at 00:21 UTC
|
my @test = ("camel","aplaca","peguin","aplaca","monkey","camel","camel
+");
my (%duplicate,%test,@redundant);
map{exists$test{$_}?$duplicate{$_}=1:$test{$_}=1}@test;
@redundant = keys %duplicate;
print "@redundant\n";
tachyon | [reply] [d/l] |