•Re: Get All Duplicated Elements in an Array (Once, without shifting)
by merlyn (Sage) on Oct 14, 2002 at 16:19 UTC
|
Just grab them only the second time they're seen.
my @result = do {
my %counter;
grep ++$counter{$_} == 2, @input;
};
-- Randal L. Schwartz, Perl hacker | [reply] [Watch: Dir/Any] [d/l] |
Re: Get All Duplicated Elements in an Array (Once, without shifting)
by John M. Dlugosz (Monsignor) on Oct 14, 2002 at 19:47 UTC
|
You could refine that to have an out list rather than an out hash. Every value you store in it has the value 1!
my %multiples;
my @out;
for (@in) {
if ($multiples{$_} == 1) {
push @out, $_;
}
$multiples{$_} = 1;
}
print "@out";
Now since it contains only one statement, you could write the if in suffix form. You could use ++ instead of setting the count to 1 in the unconditional statement.
That gets down to:
my %multiples;
my @out;
for (@in) {
push @out, $_ if ($multiples{$_}++ == 1)
}
print "@out";
That's tight enough that you can see how merlyn's form works. Just use the built-in looping mechanism of grep instead of your own foreach loop/push. It's the same thing.
He used pre-increment == 2, which you'll note is the same thing as post-increment == 1. The latter is more directly equivilent to what you had originally, but the pre-increment is arguably more efficient (though I don't know if measurably faster in Perl).
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Get All Duplicated Elements in an Array (Once, without shifting)
by Flexx (Pilgrim) on Oct 15, 2002 at 00:02 UTC
|
Of course, ++merlyns post shows what an elegant solution is... So that's the cute idiom you where asking for!
Assuming you /can|want/ not process the duplicates right away, you could save memory by omitting the extra array @out. When you go over the array for the fist time, do the counting, then do the processing separately:
my @in = qw(test foo test bar baz foo test);
my %keycount;
foreach (@in)
{
$keycount{$_}++;
# do whatever else you need to do
}
foreach (keys %keycount)
{
#print $_ if $keycount > 1;
print if $keycount{$_} > 1; # Thx, ++Aristotle!
# or do something else with $_
}
So long,
Flexx | [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] |
|
Yikes!!! Caught me with my pants way down... (you caught me back, I guess ;)
But, it works if there are no duplicates! Umm... 8)
Cheers,
Flexx
Update: struck a potentially offensive joke, that wasn't meant to be such.
| [reply] [Watch: Dir/Any] |
Re: Get All Duplicated Elements in an Array (Once, without shifting)
by ehdonhon (Curate) on Oct 14, 2002 at 22:31 UTC
|
my @in = qw/
test
foo
test
bar
baz
foo
test
/;
my %multiples;
for (@in) {
$multiples{$_}++;
}
for keys( %multiples ) {
print "$_\n" if (--$multiples{$_});
}
| [reply] [Watch: Dir/Any] [d/l] |
Re: Get All Duplicated Elements in an Array (Once, without shifting)
by thor (Priest) on Oct 15, 2002 at 00:44 UTC
|
Maybe I'm missing something, but...
for(@in){
$hash{$_}++;
}
foreach my $key (keys %hash){
print "$key is lonely\n" if ($hash{$key} == 1);
print "$key has friends\n" if ($hash{$key} != 1);
}
thor
Update: changed %hash{$_}++ to $hash{$_}++ to make it correct. | [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] |
|
While it is true that %hash{$_}++ is illegal syntax, it is interesting to note that %hash->{$_}++is not. (But it only works on actual hashes and not hash references.) AFAIK its a bug, but one that has basically become a feature.
use Data::Dumper;
use strict;
use warnings;
my %hash;
%hash->{$_}=$_ foreach 0..5;
print Dumper(\%hash);
__END__
$VAR1 = {
'0' => 0,
'1' => 1,
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5
};
It embarrassed the crap out of me when I discovered this. I was reviewing some code of my colleagues, (relatively new to perl at the time) and identified these as compile time errors. He politely told me what I was full of :-) and then showed me it compiled (and worked) fine. Luckily he had a few other subtle bugs that I found so I managed to avoid looking like a complete moron. :-)
--- demerphq
my friends call me, usually because I'm late....
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
| [reply] [Watch: Dir/Any] |
A reply falls below the community's threshold of quality. You may see it by logging in.
|