This subroutine takes all the values listed in the first array, and removes them from the second array, and returns the new (shorter) second array.

Is there a better/faster/cheaper way to do this? (I'm sure there is...) I figured it would be built-in somewhere, but couldn't find it, so I wrote it.

sub exclude { ($n, @values) = @_; @array1 = @values[0 .. $n]; @array2 = @values[$n+1 .. $#values]; foreach $entry (@array1) { @array2 = grep(!/^$entry$/, @array2); } return @array2; }

Replies are listed 'Best First'.
Re: exclude all members of @a from @b
by Beatnik (Parson) on May 13, 2001 at 20:42 UTC
    /me coughs *Perl Cookbook, Chapter 4: Arrays, section 4.8 "Computing Union, Intersection, or Difference of Unique Lists" - Examples downloadable*

    Greetz
    Beatnik
    ... Quidquid perl dictum sit, altum viditur.
Re: exclude all members of @a from @b
by Masem (Monsignor) on May 13, 2001 at 16:00 UTC
    First, most likely, you wouldn't be passing in a single array; most people in this case would use refernces to pass the arrays in and forget about having to worry about where one ends and the other begins.

    Additionally, there's no reason to invoke a regex here when a simple neq would do the job. Something like this would be better:

    sub exclude { my ($a, $b) = @_; for (1..@$a) { my $i = shift @$a; push @$a, $i if ( !grep { $_ eq $i } @$b ); } @$a; }
    Of course, with perl, TIMTOWTDI...
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain

      I'd go one step further and make a hash of the contents of @$b for lookup purposes. It's faster to look up values in a hash than in an array.

      sub exclude { my ($a, $b) = @_; my %lookup = map { $_ => undef } @$b; for (1..@$a) { my $i = shift @$a; push(@$a, $i) unless exists $lookup{$i}; } @$a; }
Re: exclude all members of @a from @b
by merlyn (Sage) on May 13, 2001 at 20:49 UTC