Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

grep an array for an element 3

Status
Not open for further replies.

nix45

MIS
Nov 21, 2002
478
US
I have two arrays like this...

Code:
@a1 = qw/1 3 5 7 9 11 13/;
@a2 = qw/1 2 3 4 5 6 7/;

I want to find out which elements in @a2 are NOT in @a1. I've tried using both grep and exists but couldn't get either one working right.

Code:
foreach $a2 (@a2) {
  @new = grep (!/$a2/, @a1);
}
print "@new\n";

@new should be equal to (2, 4, 6).


fyi, this all has to do with the other thread I started earlier today titled "comparing arrays".

Thanks,
Chris
 
I would look into using he Text::Diff module from CPAN. It will tell you what differences exist between two of just about anything.

Code:
use Text::Diff;

@a1 = qw/1 3 5 7 9 11 13/;
@a2 = qw/1 2 3 4 5 6 7/;

$comparison = diff(@a1,@a2);

print $comparison;
 
Thanks, but your script doesn't seem to work for me. I installed Text::Diff and copied and pasted what your wrote and get this..

Can't use string ("5") as a HASH ref while "strict refs" in use at /usr/lib/perl5/site_perl/5.8.0/Text/Diff.pm line 180.

I tried adding "use Text::Diff ();" afterward but got this...

Undefined subroutine &main::diff called at diff line 7.

Chris
 
My script is what you wrote, I copied and pasted it into a new script. Its 9 lines total. The error says line 180 of the diff.pm module. I get the same thing on two different computers, one Linux and one Windows.

Chris
 
ok, my bad, forgot to pass those arrays in as references. I hope it works this time.

Code:
use Text::Diff;

my @a1 = qw/1 3 5 7 9 11 13/;
my @a2 = qw/1 2 3 4 5 6 7/;

my $comparison = diff(\@a1,\@a2);

print $comparison;
 
I wrote this whilst other people replied but here it is anyway......probably a little verbose but it works :). You can make it better but I am too busy at the moment.

Code:
#!/usr/bin/perl -w

use strict;


#make our variables
my @a1 = qw/1 3 5 7 9 11 13/;
my @a2 = qw/1 2 3 4 5 6 7/;
my @new = ();


#loop through our array 2
foreach my $element(@a2)
{
        #find out if this element exists in array 1
        my $exists = grep{$_ == $element}@a1;
                #if is doesn't exist then add it to our new array
                if(!$exists)
                {
                  @new[scalar(@new)] = $element;
                }

}

#see what we got
print("@new\n");
 
To keep it simple, the problem with:
Code:
@a1 = qw/1 3 5 7 9 11 13/;
@a2 = qw/1 2 3 4 5 6 7/;

foreach $a2 (@a2) {
  @new = grep (!/$a2/, @a1);
}
print "@new\n";
is that @new is set at each iteration the previous value of @new being overwrited. At the end of the loop, @new contains all elements of @a1 except those matching the last element of a2.

What you want is something like this:
Code:
my @a1 = qw/1 3 5 7 9 11 13/;
my @a2 = qw/1 2 3 4 5 6 7/;

[COLOR=blue]# Fill @new with the values of @a1
my @new = @a1;[/color]

# For each value $a2 in @a2
foreach my $a2 (@a2) {
  # Remove from @new elements whose value is $a2
  @new = grep (!/[COLOR=blue]^[/color]$a2[COLOR=blue]$[/color]/, [COLOR=blue]@new[/color]);
}
print "@new\n";

Now at each iteration, the @new array possibly loses elements matching $a2 (I had to change the regexp to anchor it at both ends with ^ and $, otherwise for value "1" of $a2, elements "11" and "13" are removed) and at the end does not contains any element of @a2 .

Note that from the code you give, you try to find all elements of @a1 not in @a2 and not, as you said out of the code, elements of @a2 not in @a1.
So the result is "9 11 13" and not "2 4 6".
To get it the otherway just exchange all a2 and a1 in code.

--------------------

Denis
 
Any particular reason you can't copy the values from @a1 to a hash then compare the values?

Code:
my %h1;
map {$h1{$_}++} @a1;
my @new = grep(! $h1{$_}, @a2);
 
nawlej, the Text::Diff script now works but I don't even understand what the output means...

@@ -1,7 +1,7 @@
1+2 3+4 5+6 7-9-11-13

No biggie though, I have enough information to get this working now.

Thanks everyone.

Chris
 
I have a similiar problem.
I'm trying to compare 2 files and only pull out the lines in file A that don't show up in file B.

I tried using dchoulette's method but I'm getting a syntax error.

# Fill @out with the values of @later
@out = @lines;

# For each value $early in @early
foreach $word (@early) {
# Remove from @out elements whose value is $word
@out = grep -a (!/^$word$/, @out);
}
print "@out\n";
 
@a1 = qw/1 3 5 7 9 11 13/;
@a2 = qw/1 2 3 4 5 6 7/;
# elements in @a2 are NOT in @a1
#Code
%b = sort (@a2,@a2);
map {$b{$_}=undef} @a1;

#print values %b,"\n";
#OR
map {print $_," "} values %b
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top