Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

remove elements from array ref

2 views
Skip to first unread message

monkeys paw

unread,
Nov 7, 2009, 2:47:41 PM11/7/09
to
The folllowing code is supposed to remove entries from
@return_set that end in '000'. It leaves an undef in
the array instead of removing the whole element. What
fix would be best to achieve an array without 'undef'
elements? Thanks for any help!


### CODE TO REMOVE records with id =~ /000$/
my @return_set = (
{id => 'CA2345H000'},
{id => 'CA2345H100'},
{id => 'CA2345H030'},
{id => 'CA235H000'},
{id => 'CA234H001'},
);

_exclude_special_session(\@return_set);

use Data::Dumper;die 'DDDEBUG' . Dumper(\@return_set);

sub _exclude_special_session {
my $recordset = shift;
my $i;
for my $record (@{$recordset}) {
if ($record->{id} =~ /000$/) {
delete $recordset->[$i];
}
$i++;
}
}


##### HERE IS THE OUTPUT
DDDEBUG$VAR1 = [
undef,
{
'id' => 'CA2345H100'
},
{
'id' => 'CA2345H030'
},
undef,
{
'id' => 'CA234H001'
}
];

Jochen Lehmeier

unread,
Nov 7, 2009, 3:02:13 PM11/7/09
to
On Sat, 07 Nov 2009 20:47:41 +0100, monkeys paw <us...@example.net> wrote:

> The folllowing code is supposed to remove entries from
> @return_set that end in '000'. It leaves an undef in
> the array instead of removing the whole element. What
> fix would be best to achieve an array without 'undef'
> elements? Thanks for any help!

@new_set = grep { $_->{id} !~ m/000$/ } @return_set;

s...@netherlands.com

unread,
Nov 7, 2009, 3:37:25 PM11/7/09
to
On Sat, 07 Nov 2009 14:47:41 -0500, monkeys paw <us...@example.net> wrote:

>The folllowing code is supposed to remove entries from
>@return_set that end in '000'. It leaves an undef in
>the array instead of removing the whole element. What
>fix would be best to achieve an array without 'undef'
>elements? Thanks for any help!
>
>
>### CODE TO REMOVE records with id =~ /000$/
>my @return_set = (
> {id => 'CA2345H000'},
> {id => 'CA2345H100'},
> {id => 'CA2345H030'},
> {id => 'CA235H000'},
> {id => 'CA234H001'},
>);
>
>_exclude_special_session(\@return_set);
>
>use Data::Dumper;die 'DDDEBUG' . Dumper(\@return_set);
>
>sub _exclude_special_session {
> my $recordset = shift;
> my $i;
> for my $record (@{$recordset}) {
> if ($record->{id} =~ /000$/) {

splice (@{$recordset},$i,1);

> }
> $i++;
> }
>}
>
>

-sln

Uri Guttman

unread,
Nov 7, 2009, 3:41:32 PM11/7/09
to
>>>>> "mp" == monkeys paw <us...@example.net> writes:

mp> The folllowing code is supposed to remove entries from
mp> @return_set that end in '000'. It leaves an undef in
mp> the array instead of removing the whole element. What
mp> fix would be best to achieve an array without 'undef'
mp> elements? Thanks for any help!

mp> delete $recordset->[$i];

did you read the docs on delete? it is meant for use on hashes and the
docs say it leaves an undef in an array. to actually remove an element
or a set of elements from an array, splice is used. as someone else
posted, your problem is best solved by grep.

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------

Martien Verbruggen

unread,
Nov 7, 2009, 4:05:07 PM11/7/09
to

From the perlsyn documentation:

If any part of LIST is an array, "foreach" will get very confused if
you add or remove elements within the loop body, for example with
"splice". So don’t do that.

Martien
--
|
Martien Verbruggen | Since light travels faster than sound,
first...@heliotrope.com.au | is that why some people appear bright
| until you hear them speak?

s...@netherlands.com

unread,
Nov 7, 2009, 6:41:19 PM11/7/09
to
On Sun, 8 Nov 2009 08:05:07 +1100, Martien Verbruggen <martien.v...@invalid.see.sig> wrote:

>On Sat, 07 Nov 2009 12:37:25 -0800,
> s...@netherlands.com <s...@netherlands.com> wrote:
>> On Sat, 07 Nov 2009 14:47:41 -0500, monkeys paw <us...@example.net> wrote:
>>
>>>sub _exclude_special_session {
>>> my $recordset = shift;
>>> my $i;
>>> for my $record (@{$recordset}) {
>>> if ($record->{id} =~ /000$/) {
>>
>> splice (@{$recordset},$i,1);
>>
>>> }
>>> $i++;
>>> }
>
>From the perlsyn documentation:
>
> If any part of LIST is an array, "foreach" will get very confused if
> you add or remove elements within the loop body, for example with
> "splice". So don�t do that.
>
>Martien

Oh, I didn't see the LIST context.
Either one of these then.

for ( my $i=0; $i<@{$recordset}; $i++ ) {
$recordset->[$i]{id} =~ /000$/ and splice (@{$recordset},$i--,1);
}

my $i = 0;
while ( $i<@{$recordset} ) {
$recordset->[$i++]{id} =~ /000$/ and splice (@{$recordset},--$i,1);
}

-sln

Ilya Zakharevich

unread,
Nov 7, 2009, 6:46:13 PM11/7/09
to
On 2009-11-07, s...@netherlands.com <s...@netherlands.com> wrote:
>
> splice (@{$recordset},$i,1);

This is quadratic. The usual linear-time idiom is to replace the
$i-th element by the (removed) last one.

Yours,
Ilya

John W. Krahn

unread,
Nov 7, 2009, 7:09:10 PM11/7/09
to
s...@netherlands.com wrote:
> On Sun, 8 Nov 2009 08:05:07 +1100, Martien Verbruggen <martien.v...@invalid.see.sig> wrote:
>
>> On Sat, 07 Nov 2009 12:37:25 -0800,
>> s...@netherlands.com <s...@netherlands.com> wrote:
>>> On Sat, 07 Nov 2009 14:47:41 -0500, monkeys paw <us...@example.net> wrote:
>>>
>>>> sub _exclude_special_session {
>>>> my $recordset = shift;
>>>> my $i;
>>>> for my $record (@{$recordset}) {
>>>> if ($record->{id} =~ /000$/) {
>>> splice (@{$recordset},$i,1);
>>>
>>>> }
>>>> $i++;
>>>> }
>>From the perlsyn documentation:
>> If any part of LIST is an array, "foreach" will get very confused if
>> you add or remove elements within the loop body, for example with
>> "splice". So don�t do that.

>>
>> Martien
>
> Oh, I didn't see the LIST context.
> Either one of these then.
>
> for ( my $i=0; $i<@{$recordset}; $i++ ) {
> $recordset->[$i]{id} =~ /000$/ and splice (@{$recordset},$i--,1);
> }
>
> my $i = 0;
> while ( $i<@{$recordset} ) {
> $recordset->[$i++]{id} =~ /000$/ and splice (@{$recordset},--$i,1);
> }

Better to just reverse the list:

for ( my $i = $#$recordset; $i >= 0; --$i ) {
$recordset->[ $i ]{ id } =~ /000$/ and splice @$recordset, $i, 1;
}


for my $i ( reverse 0 .. $#$recordset ) {
$recordset->[ $i ]{ id } =~ /000$/ and splice @$recordset, $i, 1;
}


John
--
The programmer is fighting against the two most
destructive forces in the universe: entropy and
human stupidity. -- Damian Conway

s...@netherlands.com

unread,
Nov 7, 2009, 7:14:53 PM11/7/09
to

Not sure what you mean by this. This form of splice shrinks the array
by what, something like a memmove() in a typless way.

The solution is to do your own itterating.

Shrink with no adjustment:
for (@{$recordset}) {
$recordset->[$i]{id} =~ /000$/ and splice (@{$recordset},$i,1);
}

Shrink with adjustment:


for ( my $i=0; $i<@{$recordset}; $i++ ) {
$recordset->[$i]{id} =~ /000$/ and splice (@{$recordset},$i--,1);
}

-sln

s...@netherlands.com

unread,
Nov 7, 2009, 7:18:31 PM11/7/09
to
On Sat, 07 Nov 2009 16:09:10 -0800, "John W. Krahn" <som...@example.com> wrote:

>s...@netherlands.com wrote:
>> On Sun, 8 Nov 2009 08:05:07 +1100, Martien Verbruggen <martien.v...@invalid.see.sig> wrote:
>>
>>> On Sat, 07 Nov 2009 12:37:25 -0800,
>>> s...@netherlands.com <s...@netherlands.com> wrote:
>>>> On Sat, 07 Nov 2009 14:47:41 -0500, monkeys paw <us...@example.net> wrote:
>>>>
>>>>> sub _exclude_special_session {
>>>>> my $recordset = shift;
>>>>> my $i;
>>>>> for my $record (@{$recordset}) {
>>>>> if ($record->{id} =~ /000$/) {
>>>> splice (@{$recordset},$i,1);
>>>>
>>>>> }
>>>>> $i++;
>>>>> }
>>>From the perlsyn documentation:
>>> If any part of LIST is an array, "foreach" will get very confused if
>>> you add or remove elements within the loop body, for example with

>>> "splice". So don�t do that.


>>>
>>> Martien
>>
>> Oh, I didn't see the LIST context.
>> Either one of these then.
>>
>> for ( my $i=0; $i<@{$recordset}; $i++ ) {
>> $recordset->[$i]{id} =~ /000$/ and splice (@{$recordset},$i--,1);
>> }
>>
>> my $i = 0;
>> while ( $i<@{$recordset} ) {
>> $recordset->[$i++]{id} =~ /000$/ and splice (@{$recordset},--$i,1);
>> }
>
>Better to just reverse the list:
>
>for ( my $i = $#$recordset; $i >= 0; --$i ) {
> $recordset->[ $i ]{ id } =~ /000$/ and splice @$recordset, $i, 1;
>}
>
>
>for my $i ( reverse 0 .. $#$recordset ) {
> $recordset->[ $i ]{ id } =~ /000$/ and splice @$recordset, $i, 1;
>}
>
>
>
>
>John

Yes, much better to start at the end, don't have to move so much data.

-sln

J�rgen Exner

unread,
Nov 7, 2009, 9:18:22 PM11/7/09
to
monkeys paw <us...@example.net> wrote:
>The folllowing code is supposed to remove entries from
>@return_set that end in '000'. It leaves an undef in
>the array instead of removing the whole element. What
>fix would be best to achieve an array without 'undef'
>elements?

I would simply use a grep() instead of rolling my own code. This is
exactly the scenario it was made for.

jue

Shmuel Metz

unread,
Nov 8, 2009, 10:12:24 AM11/8/09
to
In <_8GdnRRI7Y5YU2jX...@insightbb.com>, on 11/07/2009

at 02:47 PM, monkeys paw <us...@example.net> said:

>The folllowing code is supposed to remove entries from
>@return_set that end in '000'. It leaves an undef in
>the array instead of removing the whole element.

" Note that deleting array elements in the middle of an array will not
shift the index of the ones after them down--use splice() for that."

BTW, if delete $array[$index] worked the same as splice @array,$index,1
you'd have another problem, because your $i would be wrong after the first
delete.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spam...@library.lspace.org

J Kenneth King

unread,
Nov 9, 2009, 9:40:50 AM11/9/09
to
"Jochen Lehmeier" <OJZGSR...@spammotel.com> writes:

That would be the one.

I've been away from Perl for quite a while. I sometimes forget these
idioms.

I suppose it wouldn't be hard to write a method akin to Python's
built-in filter(), but I almost took for granted that Perl doesn't have
it. The bonus to lurking on c.l.perl ;)

Thanks.

0 new messages