ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
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.
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;
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).
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.
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.
The map command you gave me (below) works awesome.
I would recommend against using it in production code .
Quote:
Originally Posted by WindowBreaker
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:
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:
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:
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).
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.
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.
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.