LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 04-20-2008, 08:24 PM   #1
WindowBreaker
Member
 
Registered: Oct 2005
Distribution: Slackware
Posts: 228

Rep: Reputation: 31
How to compare two lists (arrays) in perl


I've got two lists (1 & 2). All I need to do is remove elements from list 1 if that element is listed in list 2. Here's how I'm doing it now, but I feel it's the hard way.

Code:
for(my $i=0; $i<=$#list1; $i++){
  foreach my $element (@excludes){
    if ($list1[$i] =~ m/$element/i){
      delete $links[$i];
    }
  }
}

I know I'll feel dumb once I see how to do it better.

Thanks

PS: I'm consciously using 'delete' instead of 'splice' because I need the elements in list1 to maintain their positions.

Last edited by WindowBreaker; 04-20-2008 at 08:27 PM.
 
Old 04-20-2008, 10:13 PM   #2
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
If you want to use the same criteria as above (case-insensitive, fixed-string matches), then the method above is essentially how I would go about doing it (although I might write it with two foreach-style loops).

If, however, you want to test for exact equality of strings (not matches, and not case-insensitive), you can use the uniqueness property of hashes. E.g.,
Code:
#!/usr/bin/perl -w

use strict;

my @list1 = qw(this is a list of strings in list1);
my @list2 = qw(this is the same for the second list);

# I want @list1 to end up as: (undef, undef, "a", undef, "of", etc.)

my %seen;
$seen{$_}++ for @list2;
$seen{$_} && undef $_ for @list1;
 
Old 04-21-2008, 02:16 AM   #3
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,284

Rep: Reputation: 172Reputation: 172
work that one out!

Code:
#!/usr/bin/perl

@A = qw (tom dick harry);
@B = qw (peter paul dick harry);

@C = keys %{ { map { $_, 1} (@A, @B) } };
print "@C\n";
Code:
[billy@daffy lxq]$ ./1.pl
tom dick peter harry paul
doubtfully more efficcient, less typing,
unreadable!

Last edited by bigearsbilly; 04-21-2008 at 02:21 AM.
 
Old 04-21-2008, 01:00 PM   #4
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by bigearsbilly View Post
doubtfully more efficcient, less typing,
unreadable!
And unfortunately not what the OP wants . The code you wrote provides the mathematical operation of “set union” whereas the OP asked for “set difference”. So, to use your code style, you would want:
Code:
@C=grep!${{map{$_,1}@B}}{$_},@A;
Additionally, the OP wants the original indexing preserved, so if you originally have @A=qw(dick tom harry), the OP wants $C[1] to be "tom" (rather than $C[0]). So in that case,
Code:
@C=map{!${{map{$_,1}@B}}{$_}&&$_||undef}@A;
If you want to modify the original array, you could do:
Code:
${{map{$_,1}@B}}{$_}&&undef$_ for@A;
I should point out that the above is less efficient than my original since the same anonymous hash of @B is being created in each iteration (unless of course it is optimized out).
 
Old 04-21-2008, 01:26 PM   #5
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
See also List::Compare, which does set unions and complements (where set complement is the same thing as set difference). Unfortunately, it does not preserve indices.
 
Old 04-22-2008, 10:06 AM   #6
WindowBreaker
Member
 
Registered: Oct 2005
Distribution: Slackware
Posts: 228

Original Poster
Rep: Reputation: 31
Thanks for all the answers. The map command you gave me (below) works awesome. Now if I could only understand it.
Code:
@C=map{!${{map{$_,1}@B}}{$_}&&$_||undef}@A;
Help me understand how this works. I understand this part.
Code:
map{$_,1}@B
But what's the rest doing with it?

I understand the following part returns the element from @A if true, else returns undef.
Code:
&&$_||undef
Here's the real part I don't get.
Code:
!${{map{$_,1}@B}}{$_}
It looks as if $_, the current element from @A is used as the key in a hash. I just don't see how the ${{}} enclosing the output of the embedded map has anything to do with a hash.

Maybe I'll get it if I keep working with it, but a little help would be nice.

Last edited by WindowBreaker; 04-22-2008 at 10:29 AM.
 
Old 04-22-2008, 11:22 AM   #7
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
Apologies all: Post removed since I realized I don't see it at all. Anyone care to enlighten us?

Last edited by Telemachos; 04-22-2008 at 11:45 AM.
 
Old 04-22-2008, 01:53 PM   #8
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by WindowBreaker View Post
The map command you gave me (below) works awesome.
I would recommend against using it in production code .
Quote:
Originally Posted by WindowBreaker View Post
Here's the real part I don't get.
Code:
!${{map{$_,1}@B}}{$_}
It looks as if $_, the current element from @A is used as the key in a hash. I just don't see how the ${{}} enclosing the output of the embedded map has anything to do with a hash.
Well, when you initialize a hash to a list, every even-indexed element becomes a key and every odd-indexed element becomes a value corresponding to the key preceding it. So, if you have:
Code:
%hash = (1, 2, 3, 4);
You’ll note that $hash{1}==2 and $hash{3}==4. Likewise, the following statements produce equivalent (not equal, but semantically equivalent) hashes:
Code:
%hash1 = (map{$_,1} @B);
%hash2 = ();
$hash2{$_} = 1 for @B;
When you use curly braces ({}) around a list of items, it creates an anonymous hash with such an initialization and returns a reference to it. So the following hash references are equivalent:
Code:
%hash = (map{$_,1} @B);
$hash_ref1 = \%hash;
$hash_ref2 = { map{$_,1} @B };
If you use a sigil ($, @, or %) prior to a set of curly braces, the inside is assumed to be a reference, and the result is a dereferencing in the appropriate manner. So the following three hashes are equivalent:
Code:
%hash1 = (map{$_,1} @B);
$hash_ref = { map{$_,1} @B };
%hash2 = %{ $hash_ref };
%hash3 = %{ { map{$_,1} @B } }
If you put all these concepts together, the boolean scalars at the end are the same:
Code:
%seen = ();
$seen{$_}=1 for @B;
$harry_seen1 = $seen{"harry"};
$harry_seen2 = ${{map{$_,1}@B}}{"harry"};
Unfortunately, if you put the anonymous hash dereference inside a loop, it is created and destroyed on each iteration (which is quite a bit more work than creating a separate hash once).
 
Old 04-23-2008, 05:31 AM   #9
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,284

Rep: Reputation: 172Reputation: 172
Quote:
And unfortunately not what the OP wants . The code you wrote provides the mathematical operation of “set union” whereas the OP asked for “set difference”.
oh well! need a better spec.
Quote:
Additionally, the OP wants the original indexing preserved
he didn't say that!

anyway, i think we can agree that this is an exercise in unreadable code but interesting
in a programming exercise context.

I think the OP's original is much better as regards keeping it simple.
 
Old 04-23-2008, 05:34 AM   #10
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,284

Rep: Reputation: 172Reputation: 172
well windowbreaker,

if you find this style interesting intellectually, you should
have a go at LISP or maybe Haskell.

they are especially good at this sort of lateral thinking.
 
Old 04-23-2008, 06:44 AM   #11
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 12,132

Rep: Reputation: 987Reputation: 987Reputation: 987Reputation: 987Reputation: 987Reputation: 987Reputation: 987Reputation: 987
LISP ????... LISP ????. Shouldn't that be reducable to one line in lisp ???.

Haven't seen (as in used) that since (early) Uni days. And that was a while ago - images of PDP's wander past ...
Write a syntax parser in lisp ... foggy/drunken undergrad days evoked.
Billy, don't do that to a fella.
 
Old 04-23-2008, 06:46 AM   #12
makyo
Member
 
Registered: Aug 2006
Location: Saint Paul, MN, USA
Distribution: {Free,Open}BSD, CentOS, Debian, Fedora, Solaris, SuSE
Posts: 718

Rep: Reputation: 72
Hi.

If one uses perl a lot, the item below may be useful. Chapter 4 deals with arrays, and recipes are provided for simple and symmetric differences of arrays. The first edition can be obtained used for less than $10 ... cheers, makyo

Code:
Title: Perl Cookbook
Subtitle: Solutions and Examples for Perl Programmers
Author: Tom Christiansen, Nathan Torkington
Edition: 1st
Date: August 1998
Publisher: O'Reilly
ISBN: 1565922433
Pages: 794
Categories: perl, scripting, programming, algorithms, recipes, code
Comments: Note that a 2nd edition is available, 2003
Comments: 4.5 stars (107 reviews, 2008.04) at Amazon for 2nd
Comments: Examples tar/zip file available, see O'Reilly page.
 
Old 04-23-2008, 09:22 PM   #13
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by bigearsbilly View Post
he didn't say that!
How else do you interpret this?
Quote:
Originally Posted by WindowBreaker View Post
I need the elements in list1 to maintain their positions.
 
Old 04-24-2008, 03:01 AM   #14
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,284

Rep: Reputation: 172Reputation: 172
doh


we all have off days.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[php] how to compare 2 arrays ? graziano1968 Programming 2 11-21-2006 07:30 AM
Linked Lists vs Arrays in OS develpment NCC-1701&NCC-1701-D Programming 5 08-02-2005 12:03 PM
perl: passing 2 individual arrays/lists as args johnMG Programming 12 04-18-2005 03:49 PM
arrays in perl BBQ_Matt Programming 3 09-23-2003 07:45 AM


All times are GMT -5. The time now is 04:44 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration