CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Comparing elements in two arrays

 



sparsh
Novice

Aug 24, 2015, 6:51 AM

Post #1 of 14 (2616 views)
Comparing elements in two arrays Can't Post

Hi,

I need to compare two arrays. The elements themselves need to be matched and if there is a mismatch or an extra element in any of the arrays as compared to the other array, I need to print it out.

Any ideas on how to do this?

Sparsh


FishMonger
Veteran / Moderator

Aug 24, 2015, 8:19 AM

Post #2 of 14 (2613 views)
Re: [sparsh] Comparing elements in two arrays [In reply to] Can't Post

Before posting any question, the first thing to do is a few minutes (or seconds) of research.

http://search.cpan.org/search?query=compare&mode=all


Laurent_R
Veteran / Moderator

Aug 24, 2015, 10:58 AM

Post #3 of 14 (2608 views)
Re: [sparsh] Comparing elements in two arrays [In reply to] Can't Post

If you want help, please provide further details.

Do tour array contain numbers or strings (or both, or even other types of beasts)? Are they sorted? If not, can you sort them, or should they keep their original order?

Please show samples of the two arrays.

Do you need mismatches in both directions, or only, say, items of array A not in array B.

Also, have you tried something that failed? In which way? What did not work as expected? Please show you code, if any.

FishMonger's solution is easy and fast, but might not be acceptable for a homework assignment (just in case this is what it is).


sparsh
Novice

Aug 25, 2015, 7:10 AM

Post #4 of 14 (2570 views)
Re: [Laurent_R] Comparing elements in two arrays [In reply to] Can't Post

My apologies for being so vague. They are not sorted, and all I have to do is check if an element in one is present in the other.

i was brainstorming something like this :


Code
foreach (@drc_violations) 
{
if defined @drc_violations_eng
{
print "\nDRC Errors in QA reports and Engineering reports match\n";
}

else
{
print "\nERROR: Mismatch in DRC violations between QA and Engineering. Please check\n";

}


foreach (@erc_violations)
{
if defined @erc_violations_eng

{
print "\nERC Errors in QA reports and Engineering reports match\n";
}

else
{
print "\nERROR: Mismatch in DRC violations between QA and Engineering. Please check\n";
}
}


I'm getting some errors with defined. Is this logic correct?


(This post was edited by FishMonger on Aug 25, 2015, 7:20 AM)


FishMonger
Veteran / Moderator

Aug 25, 2015, 7:30 AM

Post #5 of 14 (2565 views)
Re: [sparsh] Comparing elements in two arrays [In reply to] Can't Post

No, the logic is wrong and you have 3 syntax errors.

You're missing the parens around both defined statements and you're missing a closing brace on the first else block.


Code
perldoc -q "How do I compute the difference of two arrays" 
Found in C:\Strawberry\perl\lib\perlfaq4.pod
How do I compute the difference of two arrays? How do I compute the intersection of two arrays?
Use a hash. Here's code to do both and more. It assumes that each
element is unique in a given array:

my (@union, @intersection, @difference);
my %count = ();
foreach my $element (@array1, @array2) { $count{$element}++ }
foreach my $element (keys %count) {
push @union, $element;
push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
}

Note that this is the *symmetric difference*, that is, all elements in
either A or in B but not in both. Think of it as an xor operation.


The example code shown in the FAQ is not exactly what you want, but it has an important clue how to solve your problem. The clue is to use a hash.

Load one of the arrays into a hash then loop over the other array and check if each value is a key in the hash. You also would need to verify that each array has the same number of elements.


(This post was edited by FishMonger on Aug 25, 2015, 7:36 AM)


Laurent_R
Veteran / Moderator

Aug 25, 2015, 9:06 AM

Post #6 of 14 (2554 views)
Re: [sparsh] Comparing elements in two arrays [In reply to] Can't Post

Hi,
sparsh sent me a PM to the following effect (I think the whole discussion is relevant to this public thread):

Quote
FishMonger's solution is needlessly complicated using a hash. Is is possible to loop through the array using a foreach() loop and then use if defined?

The array elements are unique, and not sorted (don't have to be either). Just a basic check to see if @array1 = { 1, 2,3,4} has the same elements as @array2 = {1,2,3}. (i.e I need to print out that 4 is in @array1 but not in 2).

Here is an extract of my code:


foreach (@drc_violations)
{
if (defined(@drc_violations_eng))
{
print "\nDRC Errors in QA reports and Engineering reports match\n";
}

else (@drc_violations_eng)
{
print "\nERROR: Mismatch in DRC violations between QA and Engineering. Please check\n";
}
}


foreach (@erc_violations)
{
if defined @erc_violations_eng

{
print "\nERC Errors in QA reports and Engineering reports match\n";
}

else
{
print "\nERROR: Mismatch in DRC violations between QA and Engineering. Please check\n";
}
}


And this is now my answer to him or her by PM, copied for the benefit of others reading this thread (with a minor addition and the correction of a typo):

Hi,

The logic of your code is wrong. In many respects.

Assume your arrays are array1: (1, 2, 3) and array2: (2, 3).

You go through the first loop and start with element 1. Then you check if array2 is defined, and this will always be the case, the array is defined. So your program will find that all elements of array1 are also in array2, which is obviously not the case.

If you want to do it directly with arrays, you'll need nested loops, something like this (untested):


Code
my @array1 = (1, 2, 3);  
my @array2 = (2,3);
for my $el_a1 (@array1) {
my $flag = 0; # false
for my $el_a2 (@array2) {
if ($el_a1 == $el_a2) {
$flag = 1; # found it
}
}
if (flag) {
print "common element : $el_a1\n";
else {
print "$el_a1 of array1 is missing in array2\n";
}
}

And then do it all over again the other way around to find elements of array2 not in array1.

Do you really want to do something complicated like that?

Consider now FishMonger's solution with hashes. It could basically be something like this:



Code
my @array1 = (1, 2, 3);  
my @array2 = (2,3);
my %hash2;
$hash2{$_} = 1 for @array1;
for my $item (@array1) {
if (exists $hash2{item}) {
print "common elements : $item\n"; # found it
} else {
print "Element in array 1 but not 2: $item\n";
}
}

And then the other way around, as previously.

(It could be made shorter, but I wanted to keep it very straight forward for a beginner.)

8 lines of real code for the hash solution, 13 lines for the array solution.

Do you still seriously think FishMonger's solution is more complicated?

I don't.

An additional point: the hash solution is considered the standard way of doing that not only because it is simpler, but also because, for large arrays, it is far far faster.

Final comment: the module proposed by FishMonger is essentially populating and using hashes behind the scene.

Code



      
    


FishMonger
Veteran / Moderator

Aug 25, 2015, 9:37 AM

Post #7 of 14 (2550 views)
Re: [Laurent_R] Comparing elements in two arrays [In reply to] Can't Post

To be clear, I didn't actually suggest any particular module, but instead gave a general cpan search result hoping that the OP would take a few minutes to do some research then come back with a more refined question and test code.


sparsh
Novice

Aug 25, 2015, 12:29 PM

Post #8 of 14 (2539 views)
Re: [FishMonger] Comparing elements in two arrays [In reply to] Can't Post

Thanks for the responses gentlemen. I have opted to use the array method as it makes more sense to me.

I do have a basic question now, I need to grab the 0 at the end of this sentence. :

Total number of DRC violation(s): 0

I wrote this regular expression:

if ($drc_violation_file_qa =~ m/^\s*(Total)\s*(number)\s*(of)\s*(DRC)\s*(violation)(s)(:)\s*(\d+)/)

{
$drc_violation_count_zero = $8;

}


its not grabbing the zero, meaning this if statement is failing. I suspect its something to do with the (s). Any ideas?


FishMonger
Veteran / Moderator

Aug 25, 2015, 12:47 PM

Post #9 of 14 (2535 views)
Re: [sparsh] Comparing elements in two arrays [In reply to] Can't Post

Why are you using so many capturing groups when you only want 1 value?

Do you only want to match a zero or do you want to match any value?


sparsh
Novice

Aug 25, 2015, 12:48 PM

Post #10 of 14 (2532 views)
Re: [FishMonger] Comparing elements in two arrays [In reply to] Can't Post

Only want to match the zero. As for the capturing groups, aren't those necessary to help the program know its grabbed the correct line?


FishMonger
Veteran / Moderator

Aug 25, 2015, 12:52 PM

Post #11 of 14 (2527 views)
Re: [sparsh] Comparing elements in two arrays [In reply to] Can't Post

You don't need any capturing groups. You only need to know if it matches.


Code
my $drc_violation_file_qa = 'Total number of DRC violation(s): 0'; 

if ($drc_violation_file_qa =~ /^Total number of DRC violation\D+0$/) {
my $drc_violation_count = 0;
print "drc violation count = $drc_violation_count\n";
}
else {
print "no match\n";
}


Instead of using \D+ in the regex, you could be more explicit.

Code
/^Total number of DRC violation\(s\):\s*0$/



(This post was edited by FishMonger on Aug 25, 2015, 12:54 PM)


sparsh
Novice

Aug 25, 2015, 1:17 PM

Post #12 of 14 (2523 views)
Re: [FishMonger] Comparing elements in two arrays [In reply to] Can't Post

Actually on second thought, I need to grab that zero at the end and store it. I don't understand why you set a variable to 0. Could you explain the reasoning behind that please? I would really appreciate it.


FishMonger
Veteran / Moderator

Aug 25, 2015, 1:26 PM

Post #13 of 14 (2520 views)
Re: [sparsh] Comparing elements in two arrays [In reply to] Can't Post

You said that you're only needing to match the zero. Since you were assigning the 0 value to a var, I did the same but hard coded the zero instead of using capturing parens and $1. You can do it either way.

If you need to capture the number no matter what value it is, then you need to use the capturing parens and $1 when saving it to a var.


Laurent_R
Veteran / Moderator

Aug 27, 2015, 3:08 AM

Post #14 of 14 (2490 views)
Re: [sparsh] Comparing elements in two arrays [In reply to] Can't Post


In Reply To
I have opted to use the array method as it makes more sense to me.


Sorry to say that, but it is a bit silly and very inefficient if your input is large. With large input, doubly-nested loops with the array solution can make the process thousands of times slower.

If you interested in learning to write Perl code, you should learn the idiomatic ways of efficiently solving problem. There is nothing complicated or counterintuitive with the hash solution, it is actually simpler.

Now, of course, it is your choice if you want to use a working but crippled solution rather than an efficient one.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives