Home > Archive > PERL Beginners > May 2004 > removing element of array
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
removing element of array
|
|
| Andrew Gaffney 2004-05-14, 8:30 pm |
| I have an array that I need to remove an element from the middle of. Is there a
one-liner way to do this?
--
Andrew Gaffney
Network Administrator
Skyline Aeronautics, LLC.
636-357-1548
| |
| Andrew Gaffney 2004-05-14, 8:30 pm |
| Wiggins d'Anconia wrote:
> Andrew Gaffney wrote:
>
>
> perldoc -f delete
> perldoc -f splice
>
> Helps?
A little, but I don't know how to put it all together.
--
Andrew Gaffney
Network Administrator
Skyline Aeronautics, LLC.
636-357-1548
| |
| Wiggins D'Anconia 2004-05-14, 8:30 pm |
| Andrew Gaffney wrote:
> I have an array that I need to remove an element from the middle of. Is
> there a one-liner way to do this?
>
perldoc -f delete
perldoc -f splice
Helps?
http://danconia.org
| |
| Andrew Gaffney 2004-05-14, 9:30 pm |
| Andrew Gaffney wrote:
> Wiggins d'Anconia wrote:
>
>
>
> A little, but I don't know how to put it all together.
I tried to write a small test script to figure this out, but I can't get
anywhere. I used array references in my test program, because I need to pull out
an element from an array through a ref and assign the result back to the same
array ref. Here's what I've got:
#!/usr/bin/perl
use strict;
use warnings;
my $array1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
my $array2 = \@{splice @{$array1}, 0, 6};
my $array3 = \@{splice @{$array1}, 7};
push @{$array2}, @{$array3};
print join ', ', @{$array1} . "\n";
This gives me the following when I run it:
Can't use string ("5") as an ARRAY ref while "strict refs" in use at ./array.pl
line 8.
What am I doing wrong?
--
Andrew Gaffney
Network Administrator
Skyline Aeronautics, LLC.
636-357-1548
| |
| Charles K. Clarkson 2004-05-14, 10:30 pm |
| Andrew Gaffney <agaffney@skylineaero.com> wrote:
:
: I tried to write a small test script to figure this out,
: but I can't get anywhere. I used array references in my
: test program, because I need to pull out an element from
: an array through a ref and assign the result back to the
: same array ref.
I don't understand what result you want to assign to
the original array ref. Give us an example of what you want
to end up with and we can get you there.
Starting with this:
: my $array1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
End up with:
$array1 = ???
$array2 = ???
$array3 = ???
HTH,
Charles K. Clarkson
--
Mobile Homes Specialist
254 968-8328
| |
| Andrew Gaffney 2004-05-14, 10:30 pm |
| Charles K. Clarkson wrote:
> Andrew Gaffney <agaffney@skylineaero.com> wrote:
> :
> : I tried to write a small test script to figure this out,
> : but I can't get anywhere. I used array references in my
> : test program, because I need to pull out an element from
> : an array through a ref and assign the result back to the
> : same array ref.
>
> I don't understand what result you want to assign to
> the original array ref. Give us an example of what you want
> to end up with and we can get you there.
>
> Starting with this:
>
> : my $array1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
>
> End up with:
>
> $array1 = ???
> $array2 = ???
> $array3 = ???
I was just using those as temporary variables. Basically, I want to end up with
an array that is [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15] (missing
the 7th element in this case). I'm just trying to figure out how to remove an
arbitrary element from an array and not leave an empty space.
--
Andrew Gaffney
Network Administrator
Skyline Aeronautics, LLC.
636-357-1548
| |
| Charles K. Clarkson 2004-05-14, 10:30 pm |
| Andrew Gaffney <agaffney@skylineaero.com> wrote:
:
: Charles K. Clarkson wrote:
: >
: > I don't understand what result you want to assign to
: > the original array ref. Give us an example of what you want
: > to end up with and we can get you there.
: >
: > Starting with this:
: >
: > : my $array1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
: 13, 14, 15];
: >
: > End up with:
: >
: > $array1 = ???
: > $array2 = ???
: > $array3 = ???
:
: I was just using those as temporary variables. Basically, I
: want to end up with an array that is [0, 1, 2, 3, 4, 5, 7, 8,
: 9, 10, 11, 12, 13, 14, 15] (missing the 7th element in this
: case). I'm just trying to figure out how to remove an
: arbitrary element from an array and not leave an empty space.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper 'Dumper';
my $array1 = [0 .. 15];
print Dumper $array1;
splice @$array1, 6, 1;
print Dumper $array1;
__END__
HTH,
Charles K. Clarkson
--
Mobile Homes Specialist
254 968-8328
| |
| Andrew Gaffney 2004-05-15, 12:30 am |
| Charles K. Clarkson wrote:
> Andrew Gaffney <agaffney@skylineaero.com> wrote:
> :
> : Charles K. Clarkson wrote:
> : >
> : > I don't understand what result you want to assign to
> : > the original array ref. Give us an example of what you want
> : > to end up with and we can get you there.
> : >
> : > Starting with this:
> : >
> : > : my $array1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
> : 13, 14, 15];
> : >
> : > End up with:
> : >
> : > $array1 = ???
> : > $array2 = ???
> : > $array3 = ???
> :
> : I was just using those as temporary variables. Basically, I
> : want to end up with an array that is [0, 1, 2, 3, 4, 5, 7, 8,
> : 9, 10, 11, 12, 13, 14, 15] (missing the 7th element in this
> : case). I'm just trying to figure out how to remove an
> : arbitrary element from an array and not leave an empty space.
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
> use Data::Dumper 'Dumper';
>
> my $array1 = [0 .. 15];
>
> print Dumper $array1;
>
> splice @$array1, 6, 1;
>
> print Dumper $array1;
I've modified your code to be more like it is in my program:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper 'Dumper';
my $array1 = ['test1', 'test2', 'test3', 'test4', '!test5', 'test6', 'test7'];
print Dumper $array1;
for my $lv (0..$#{$array1}) {
splice @$array1, $lv, 1 if($array1->[$lv] =~ /^!/);
}
print Dumper $array1;
This doesn't quite work because I'm removing elements from the array I'm looping
through. What would be the best way to take care of this? Would it work to set
elements to remove to undef and then remove them afterwards by iterating through
the array backwards (to not change the array indexes relative to the beginning)?
for my $lv (0..$#{$array1}) {
$array1->[$lv] = undef if($array1->[$lv] =~ /^!/);
}
for my $lv ($#{$array1}..0) {
splice @$array1, $lv, 1 if(! defined $array1->[$lv]);
}
Would this work as I think it would?
--
Andrew Gaffney
Network Administrator
Skyline Aeronautics, LLC.
636-357-1548
| |
| Andrew Gaffney 2004-05-15, 12:30 am |
| Andrew Gaffney wrote:
> Charles K. Clarkson wrote:
>
>
>
> I've modified your code to be more like it is in my program:
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
> use Data::Dumper 'Dumper';
>
> my $array1 = ['test1', 'test2', 'test3', 'test4', '!test5', 'test6',
> 'test7'];
>
> print Dumper $array1;
>
> for my $lv (0..$#{$array1}) {
> splice @$array1, $lv, 1 if($array1->[$lv] =~ /^!/);
> }
>
> print Dumper $array1;
>
> This doesn't quite work because I'm removing elements from the array I'm
> looping through. What would be the best way to take care of this? Would
> it work to set elements to remove to undef and then remove them
> afterwards by iterating through the array backwards (to not change the
> array indexes relative to the beginning)?
>
> for my $lv (0..$#{$array1}) {
> $array1->[$lv] = undef if($array1->[$lv] =~ /^!/);
> }
>
> for my $lv ($#{$array1}..0) {
> splice @$array1, $lv, 1 if(! defined $array1->[$lv]);
> }
>
> Would this work as I think it would?
To answer myself: No. But the following works:
for my $lv (0..$#{$array1}) {
$array1->[$lv] = undef if($array1->[$lv] =~ /^!/);
}
for my $lv (-($#{$array1})..0) {
$lv = abs($lv);
if(! defined $array1->[$lv]) {
splice @$array1, $lv, 1;
}
}
Perl wouldn't let me count backwards in a for() loop, so I worked around it by
negatizing the start and using abs() to convert it back to the positive array
index. It worked perfectly.
--
Andrew Gaffney
Network Administrator
Skyline Aeronautics, LLC.
636-357-1548
| |
| Charles K. Clarkson 2004-05-15, 12:30 am |
| Andrew Gaffney <agaffney@skylineaero.com> wrote:
:
: I've modified your code to be more like it is in my program:
:
: #!/usr/bin/perl
:
: use strict;
: use warnings;
: use Data::Dumper 'Dumper';
:
: my $array1 = ['test1', 'test2', 'test3', 'test4', '!test5',
: 'test6', 'test7'];
:
: print Dumper $array1;
:
: for my $lv (0..$#{$array1}) {
: splice @$array1, $lv, 1 if($array1->[$lv] =~ /^!/);
: }
:
: print Dumper $array1;
:
: This doesn't quite work because I'm removing elements
: from the array I'm looping through. What would be the
: best way to take care of this?
Don't use splice: :)
print Dumper $array1;
@$array1 = grep ! /^!/, @$array1;
print Dumper $array1;
HTH,
Charles K. Clarkson
--
Mobile Homes Specialist
254 968-8328
| |
| Andrew Gaffney 2004-05-15, 12:30 am |
| Charles K. Clarkson wrote:
> Andrew Gaffney <agaffney@skylineaero.com> wrote:
> :
> : I've modified your code to be more like it is in my program:
> :
> : #!/usr/bin/perl
> :
> : use strict;
> : use warnings;
> : use Data::Dumper 'Dumper';
> :
> : my $array1 = ['test1', 'test2', 'test3', 'test4', '!test5',
> : 'test6', 'test7'];
> :
> : print Dumper $array1;
> :
> : for my $lv (0..$#{$array1}) {
> : splice @$array1, $lv, 1 if($array1->[$lv] =~ /^!/);
> : }
> :
> : print Dumper $array1;
> :
> : This doesn't quite work because I'm removing elements
> : from the array I'm looping through. What would be the
> : best way to take care of this?
>
>
> Don't use splice: :)
>
> print Dumper $array1;
>
> @$array1 = grep ! /^!/, @$array1;
>
> print Dumper $array1;
Well, I'm working with the data in the array at the same time I'm trying to
remove certain elements. I need to process the elements that start with a '!'
and then remove them. I process all other elements differently.
--
Andrew Gaffney
Network Administrator
Skyline Aeronautics, LLC.
636-357-1548
| |
| Charles K. Clarkson 2004-05-15, 1:30 am |
| Andrew Gaffney <agaffney@skylineaero.com> wrote:
:
: Charles K. Clarkson wrote:
: >
: > print Dumper $array1;
: >
: > @$array1 = grep ! /^!/, @$array1;
: >
: > print Dumper $array1;
:
: Well, I'm working with the data in the array at the same
: time I'm trying to remove certain elements. I need to
: process the elements that start with a '!' and then
: remove them. I process all other elements differently.
Sure. Now you tell me:
( $array1, my $array2 ) = unmerge( $array1 );
print Dumper $array1, $array2;
sub unmerge {
my( @arr1, @arr2 );
/^!/ ? push @arr1, $_ : push @arr2, $_ foreach @{ $_[0] };
return ( \@arr1, \@arr2 );
}
Or:
my( $array2, $array3 );
/^!/ ? push @$array2, $_ : push @$array3, $_ foreach @$array1;
print Dumper $array2, $array3;
HTH,
Charles K. Clarkson
--
Mobile Homes Specialist
254 968-8328
| |
| Jeff 'Japhy' Pinyan 2004-05-15, 1:30 am |
| On May 14, Charles K. Clarkson said:
>sub unmerge {
> my( @arr1, @arr2 );
> /^!/ ? push @arr1, $_ : push @arr2, $_ foreach @{ $_[0] };
I like this better:
push @{ /^!/ ? \@arr1 : \@arr2 }, $_ for @{ $_[0] };
> return ( \@arr1, \@arr2 );
>}
--
Jeff "japhy" Pinyan japhy@pobox.com http://www.pobox.com/~japhy/
RPI Acacia brother #734 http://www.perlmonks.org/ http://www.cpan.org/
CPAN ID: PINYAN [Need a programmer? If you like my work, let me know.]
<stu> what does y/// stand for? <tenderpuss> why, yansliterate of course.
| |
| Charles K. Clarkson 2004-05-15, 1:30 am |
| Jeff 'japhy' Pinyan [mailto:japhy@perlmonk.org]
:
: On May 14, Charles K. Clarkson said:
:
: >sub unmerge {
: > my( @arr1, @arr2 );
: > /^!/ ? push @arr1, $_ : push @arr2, $_ foreach @{ $_[0] };
:
: I like this better:
:
: push @{ /^!/ ? \@arr1 : \@arr2 }, $_ for @{ $_[0] };
Arghh! I tried a few variations of that and couldn't
get it to work.
Thanks Jeff,
Charles K. Clarkson
--
Mobile Homes Specialist
254 968-8328
| |
| David Storrs 2004-05-16, 8:30 am |
| On Fri, May 14, 2004 at 10:35:45PM -0500, Andrew Gaffney wrote:
> Charles K. Clarkson wrote:
Note that using grep constructs a whole new array and is potentially
very slow if working with large arrays--especially if the array is
tied to (e.g.) a database.
Which is not to say you _shouldn't_ use grep...just make sure you know
something about the size of your data. I use a 'for' loop below,
which will have the same problem.
[color=darkred]
> Well, I'm working with the data in the array at the same time I'm trying to
> remove certain elements. I need to process the elements that start with a
> '!' and then remove them. I process all other elements differently.
This should do what you want. It also does it in one pass, and
without counting backward or any other fancy tricks.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my $a = [qw(foo bar baz !jaz frob quux)];
print Dumper $a;
my $i = 0;
for (@$a) {
unless ( /^!/ ) {
process_normal_item($_);
$i++;
} else {
process_negated_item($_);
splice @$a, $i, 1;
$_ = $a->[$i];
redo;
}
}
print Dumper $a;
# These are only here to provide you with convenient hooks for
# expanding this into your own code.
#
sub process_normal_item { print shift; }
sub process_negated_item { print shift; }
|
|
|
|
|