Re: Removing elemets from an array
by linuxer (Curate) on Dec 28, 2012 at 08:18 UTC
|
The hint to perlfaq4 is excellent.
Use a hash and grep() and you are fine. No need for delete() or splice() here.
#! /usr/bin/perl
use strict;
use warnings;
my @arcb = ( 450, 625, 720, 645 );
my @arca = ( 625, 645 );
### see perlfaq4 - How can I remove duplicate elements from a list or
+array?
my %unwanted; ### or %seen as in the faq4
$unwanted{$_}++ for @arca;
@arcb = grep { !$unwanted{$_} } @arcb;
print "@arcb\n";
+
__END__
Updates
| [reply] [d/l] |
|
Worked perferctly for me :) Thankyou
| [reply] |
Re: Removing elemets from an array
by davido (Cardinal) on Dec 28, 2012 at 10:17 UTC
|
my @arcb = ( 450, 625, 720, 645 );
my @arca = ( 625, 645 );
@arcb = do {
my %exclude;
@exclude{@arca} = ();
grep { ! exists $exclude{$_} } @arcb;
};
print "@arcb\n";
grep, and a narrowly scoped hash populated via a slice.
| [reply] [d/l] |
Re: Removing elemets from an array
by Anonymous Monk on Dec 28, 2012 at 05:54 UTC
|
| [reply] |
|
Bit confusing with the reference,It is sure that the elements of @arca are in @arcb,but here am not having any indexes of those elements, but I need to remove them from the array @arcb.
| [reply] |
|
| [reply] |
Re: Removing elemets from an array
by nithins (Sexton) on Dec 28, 2012 at 06:38 UTC
|
#!/usr/bin/perl
use strict;
my @arcb= (450,625,720,645);
my @arca=(625,645);
foreach my $a (@arca){
for(my $i=0;$i<scalar(@arcb);$i++){
delete $arcb[$i] if($a==$arcb[$i]);
}
}
print "@arcb";
hope this is what you were looking for.... | [reply] [d/l] |
|
| [reply] |
|
Thankyou,it worked for me,
I heard that delete should be used only with hash,it might cause some problems when used with arrays.
is it true?I can use this?
| [reply] |
|
| [reply] |
Re: Removing elemets from an array
by LanX (Saint) on Dec 28, 2012 at 13:07 UTC
|
DB<109> @arcb = ( 450, 625, 720, 645 );
=> (450, 625, 720, 645)
DB<110> @arca = ( 625, 645 );
=> (625, 645)
DB<111> @arcb{@arcb}=();
=> (undef, undef, undef, undef)
DB<112> @arca{@arca}=(); # EDIT: ehm ... sorry useless line...
+
=> (undef, undef)
DB<113> delete @arcb{@arca}
=> (undef, undef)
DB<114> @arcb=keys %arcb
=> (450, 720)
| [reply] [d/l] |
Re: Removing elemets from an array
by karlgoethebier (Abbot) on Dec 28, 2012 at 16:51 UTC
|
#!/usr/bin/perl
+
use strict;
use warnings;
use Set::Scalar;
use Data::Dumper;
my @arcb = ( 450, 625, 720, 645 );
my @arca = ( 625, 645 );
my $s1 = Set::Scalar->new(@arcb);
my $s2 = Set::Scalar->new(@arca);
@arcb = @{ $s1 - $s2 };
print Dumper( \@arcb );
__END__
$VAR1 = [
450,
720
];
Regards, Karl
P.S.: No, i don't get paid for endorsement of Set::Scalar ;-)
And yes, i'm repeating myself: Re: Is it possible to find the matching words and the percentage of matching words between two texts?
Update
«The Crux of the Biscuit is the Apostrophe»
| [reply] [d/l] [select] |
|
#! /usr/bin/perl -l
+
use strict;
+
use warnings;
+
+
our @array = ( 1 .. 5 );
+
+
sub foo {
+
our @array;
+
+
print " inside before modification: @array";
+
+
# work with @array and modify it
+
@array = ( 'a' .. 'e' );
+
+
print " inside after modification: @array";
+
}
+
+
# now do the work
+
print "outside before calling foo(): @array";
+
foo();
+
print "outside after calling foo(): @array";
This results in:
outside before calling foo(): 1 2 3 4 5
inside before modification: 1 2 3 4 5
inside after modification: a b c d e
outside after calling foo(): a b c d e
As one can see, outside the sub, the array is changed as well.
So afterTransferred to your benchmark script: With the first call of the first subroutine, the data arrays are modified. All following calls use that modified data and might change the data again. This might produce erroneous benchmark results.
In the current setting, this might be not very severe. But there might be situations, where this is fatal!
You should use separate arrays inside your sub routines (my @work = @array;), or localize the variables (local @array = @array;) inside the sub routines.
| [reply] [d/l] [select] |
|
"I hope you are aware, that your subroutines modify the data arrays globally?"
Actually yes. Please don't ask why i did it this way ;-)
Thanks, HNY and best regards, Karl
«The Crux of the Biscuit is the Apostrophe»
| [reply] |
|
| [reply] |
|
Update: Thanks to linuxer for pointing out that the original data were modified by the functions and therefore after the first call the other functions had a smaller data set. Here is the corrected version and the results.
Updated again: realized I had warnings turned on and the nithins code warnings slowed down the benchmark a bunch when they printed to STDERR. Fixed the nithins approach.
As I've seen BrowserUK do before I replaced the toy data set with something more realistic and the nithins approach became the slowest.
I started with 10^6 and then 10^5 elements in the range but got warnings about too few iterations to make a comparison.
#!/usr/bin/perl
+
use Benchmark qw ( :hireswallclock cmpthese timethese );
use strict;
# use warnings;
use Set::Scalar;
use Data::Dumper;
use List::Compare;
# our @arcb = ( 450, 625, 720, 645 );
# our @arca = ( 625, 645 );
our @arcb = grep {$_ % 2} (1..10000);
our @arca = grep {not $_ % 5} (1..10000);
sub davido {
#our @arcb;
#our @arca;
local @arcb = @arcb;
local @arca = @arca;
@arcb = do {
my %exclude;
@exclude{@arca} = ();
grep { !exists $exclude{$_} } @arcb;
};
# print "@arcb\n";
}
sub karlgoethebier {
#our @arcb;
#our @arca;
local @arcb = @arcb;
local @arca = @arca;
my $s1 = Set::Scalar->new(@arcb);
my $s2 = Set::Scalar->new(@arca);
@arcb = @{ $s1 - $s2 };
# print Dumper( \@arcb );
}
sub Lotus1 {
#our @arcb;
#our @arca;
local @arcb = @arcb;
local @arca = @arca;
my $lc = List::Compare->new( \@arca, \@arcb );
@arcb = $lc->get_Ronly;
# print "arcb: @arcb\n";
}
sub LanX {
my ( %arcb, %arca );
#our @arcb;
#our @arca;
local @arcb = @arcb;
local @arca = @arca;
@arcb{@arcb} = ();
# @arca{@arca} = (); update here
delete @arcb{@arca};
@arcb = keys %arcb;
# print Dumper( \@arcb );
}
sub linuxer {
#our @arcb;
#our @arca;
local @arcb = @arcb;
local @arca = @arca;
my %unwanted;
$unwanted{$_}++ for @arca;
@arcb = grep { !$unwanted{$_} } @arcb;
# print "@arcb\n";
}
sub nithins {
#our @arcb;
#our @arca;
local @arcb = @arcb;
local @arca = @arca;
foreach my $a (@arca) {
for ( my $i = 0 ; $i < scalar(@arcb) ; $i++ ) {
#delete $arcb[$i] if ( $a == $arcb[$i] );
#fixed the warnings by using splice
splice @arcb,$i,1 if ( $a == $arcb[$i] );
}
}
# print "@arcb";
}
# karlgoethebier;
# Lotus1;
# LanX;
# davido;
# linuxer;
# nithins;
my $results = timethese(
-20,
{
'karlgoethebier' => 'karlgoethebier',
'Lotus1' => 'Lotus1',
'LanX' => 'LanX',
'davido' => 'davido',
'linuxer' => 'linuxer',
'nithins' => 'nithins',
}
);
cmpthese($results);
__END__
Benchmark: running LanX, Lotus1, davido, karlgoethebier, linuxer, nith
+ins for at least 20 CPU seconds...
LanX: 21.5303 wallclock secs (21.14 usr + 0.38 sys = 21.52 CPU)
+ @ 143.25/s (n=3082)
Lotus1: 20.4152 wallclock secs (20.27 usr + 0.14 sys = 20.41 CPU)
+ @ 24.55/s (n=501)
davido: 20.1223 wallclock secs (19.72 usr + 0.38 sys = 20.09 CPU)
+ @ 110.78/s (n=2226)
karlgoethebier: 22.1035 wallclock secs (22.06 usr + 0.03 sys = 22.09
+CPU) @ 22.22/s (n=491)
linuxer: 21.5713 wallclock secs (21.14 usr + 0.42 sys = 21.56 CPU)
+ @ 147.39/s (n=3178)
nithins: 21.1337 wallclock secs (21.09 usr + 0.00 sys = 21.09 CPU)
+ @ 0.66/s (n=14)
Rate nithins karlgoethebier Lotus1 davido La
+nX linuxer
nithins 0.664/s -- -97% -97% -99% -10
+0% -100%
karlgoethebier 22.2/s 3248% -- -9% -80% -8
+4% -85%
Lotus1 24.6/s 3599% 10% -- -78% -8
+3% -83%
davido 111/s 16590% 398% 351% -- -2
+3% -25%
LanX 143/s 21482% 545% 483% 29%
+-- -3%
linuxer 147/s 22106% 563% 500% 33%
+3% --
Note: the results below are the original version with the modified dat
+a sets from the commented out 'our' array declarations.
Benchmark: running LanX, Lotus1, davido, karlgoethebier, linuxer, nith
+ins for at least 20 CPU seconds...
LanX: 24.0026 wallclock secs (22.73 usr + 0.00 sys = 22.73 CPU)
+ @ 608.25/s (n=13828)
Lotus1: 22.2431 wallclock secs (21.50 usr + 0.30 sys = 21.80 CPU)
+ @ 27.53/s (n=600)
davido: 20.17 wallclock secs (19.81 usr + 0.33 sys = 20.14 CPU) @
+ 199.25/s (n=4013)
karlgoethebier: 20.2918 wallclock secs (19.95 usr + 0.33 sys = 20.28
+CPU) @ 14.35/s (n=291)
linuxer: 20.1558 wallclock secs (19.87 usr + 0.26 sys = 20.14 CPU)
+ @ 321.91/s (n=6483)
nithins: 20.9194 wallclock secs (20.89 usr + 0.00 sys = 20.89 CPU)
+ @ 0.77/s (n=16)
Rate nithins karlgoethebier Lotus1 davido linuxe
+r LanX
nithins 0.766/s -- -95% -97% -100% -100
+% -100%
karlgoethebier 14.3/s 1773% -- -48% -93% -96
+% -98%
Lotus1 27.5/s 3494% 92% -- -86% -91
+% -95%
davido 199/s 25915% 1289% 624% -- -38
+% -67%
linuxer 322/s 41932% 2144% 1069% 62% -
+- -47%
LanX 608/s 79319% 4139% 2110% 205% 89
+% --
updated with LanX's update | [reply] [d/l] |
|
| [reply] |
|
|
|
|
Re: Removing elemets from an array
by Lotus1 (Vicar) on Dec 28, 2012 at 16:43 UTC
|
#!/usr/bin/perl
use warnings;
use strict;
use List::Compare;
my @arca = qw( 625 645 );
my @arcb = qw( 450 625 720 645 );
print "arcb: @arcb\n";
my $lc = List::Compare->new( \@arca, \@arcb);
# get the items which appear only in the second list.
@arcb = $lc->get_Ronly;
print "arcb: @arcb\n";
| [reply] [d/l] |