Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

how to rm an element from an array?

by waxmop (Beadle)
on Oct 28, 2002 at 01:14 UTC ( #208423=perlquestion: print w/replies, xml ) Need Help??
waxmop has asked for the wisdom of the Perl Monks concerning the following question:

Here's what I want to accomplish:

my @arr = qw(aa bb cc); my $var = "aa"; yoink(@arr, $var); print "@arr\n"; # now, @arr is qw(bb cc);

The yoink() function would remove from the array any elements that match the $var variable.

Is there a function to accomplish this already? I'm about to write "yoink()", but before I do, I thought I'd check with the resident geniuses around here.

Thanks as always.

Replies are listed 'Best First'.
Re: how to rm an element from an array?
by I0 (Priest) on Oct 28, 2002 at 01:25 UTC
    @arr=grep $_ ne $var, @arr;
Re: how to rm an element from an array?
by graff (Chancellor) on Oct 28, 2002 at 01:41 UTC
    I'd suggest a different call sequence for "yoink()":
    yoink( \@arr, $var ); # pass an array ref and a scalar
    The sub definition could go something like this, if you don't mind making a copy of the array in order to do the work:
    sub yoink { my ($arr_ref, $kill_pattern) = @_; my @out_arr; for (@$arr_ref) { push @out_arr, $_ unless (/^$kill_pattern$/) } @$arr_ref = @out_arr; }
    The "yoink" could also use the "splice" function (see perldoc -f splice) to edit the array in place; I suspect the "optimal" choice would depend on array size and number of elements being removed -- with big arrays, doing just a few edits will go best with splice, but doing lots of edits might go quicker using selective copying to a separate array. (For small arrays, there won't be a noticeable difference.)

    update: IO's solution is better than mine, of course. (I just forgot that I should've known better...)

      Why not a combination of the two solutions, something like:

      sub yoink { my ($array_ref, @kill_patterns) = @_; foreach my $kp (@kill_patterns) { @{$array_ref} = grep $_ ne $kp, @{$array_ref}; } }
      That way, you could call it with one or more kill patterns, such as &yoink(\@arr, $kp), or &yoink(\@arr, $kp1, $kp2, $kp3), or so forth... (At least, I think it would work....)
        If you always want to modify the original array, you could use function prototypes (let the scolding begin!) and use yoink like a builtin. That way, you wouldn't have to keep passing \@arr as a ref like that. However, if you want to keep the original array intact and let yoink return a separate copy with the proper yoinkage, then this is certainly not at all what you want.
        sub yoink(\@$) { my ($array_ref, $remove) = @_; @$array_ref = grep { $_ ne $remove } @$array_ref; } my @arr = qw/un deux trois quatre cinq six sept huit/; # no passing of \@arr -- oh, so pretty! yoink @arr, 'deux'; print "@arr\n"; __END__ un trois quatre cinq six sept huit


Re: how to rm an element from an array?
by Revelation (Deacon) on Oct 28, 2002 at 03:30 UTC
    I don't do this personally, but the delete function can be used, instead of grep, if you want to preserve the array indices:
    perldoc -f delete
    Given an expression that specifies a hash element, array element, hash slice, or array slice, deletes the specified element(s) from the hash or array. In the case of an array, if the array elements happen to be at the end, the size of the array will shrink to the highest element that tests true for exists() (or 0 if no such element exists).
    for (0..$#arr) {delete($arr[$_]) if $arr[$_] eq $var;};
    I'd use grep, otherwise (IO has provided an example of how to use grep).

    Gyan Kapur
Re: how to rm an element from an array?
by jdporter (Canon) on Oct 28, 2002 at 17:53 UTC
    Unless you have bigger plans for that yoink(), I'd scrap it altogether and just use straight, natural, intrinsic perl.

    Start with IO's solution. Then you can extend the pattern-matching part as needed. And avoid the obfuscation of intent caused by using yoink().

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://208423]
Approved by graff
Front-paged by tye
[Lady_Aleena]: Discipulus, it is at 2 now, but with what I am thinking about, it could go to 3. However, only 1 is needed. The second and third are optional.
[shmem]: straight list or named parameters - that depends on whether (and how many) optional arguments you have
[Discipulus]: if so a plain list is ok, imho
[Lady_Aleena]: shmem, I already have the plugin installed, just not active.
[shmem]: if you have 1 optional argument, place that at the end of the list. If you have more, go for named parameters.
[Lady_Aleena]: 1 manditory, 2 optional.
[Discipulus]: my ($need,$opta,$optb ) = @_; .. if $opta..
[shmem]: all else leads to trouble, even if the third argument depends on the existence of the second. That may become brittle.
[Discipulus]: but if have case like subname(15,undef,3 ) maybe bettere named parameters
[Lady_Aleena]: I don't want to have to do: alpha_menu($hash, undef, $type);

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (12)
As of 2017-04-27 12:19 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (506 votes). Check out past polls.