Re: Difference Quantity of two Arrays
by ikegami (Patriarch) on Jan 02, 2007 at 14:40 UTC
|
The 1st pass through map allows "user" and "smtp". ("fetch" would be skipped.)
The 2nd pass through map allows "user" and "smtp". ("forward" would be skipped.)
The 3rd pass through map allows "smtp". ("user" is skipped.)
The 4th pass through map allows "user". ("smtp" is skipped.)
One solution (Set arithmetic using a hash):
sub create_list {
my %dbs = map { $_ => 1 } qw/fetch forward user smtp/;
delete @dbs{@_};
return keys %dbs;
}
Another solution (Set arithmetic using a superposition):
use Quantum::Superpositions;
sub create_list {
my $dbs = any qw/fetch forward user smtp/;
my $skip = all @_;
return eigenstates( $dbs ne $skip );
}
Another solution (Set arithmetic using sets [seemed appropriate at the time]):
use Set::Scalar qw( );
sub create_list {
my $dbs = Set::Scalar->new( qw/fetch forward user smtp/ );
my $skip = Set::Scalar->new( @_ );
return ($dbs - $skip)->members();
}
Update: Added second and third snippet.
| [reply] [d/l] [select] |
|
|
Thank you for your explanation.
My Perl book says, that delete deletes a key value pair. But it doesn't tell me why I have to use @dbs{@_} instead of $dbs{@_} (which apparently does nothing) or %dbs{@_} (which throws a failure) to get the thing working. Can you explain? :)
| [reply] |
|
|
$ means you're working with one element.
@ means you're working with multiple elements.
@hash{@list}
is a hash slice. It amounts to
map { $hash{$_} } @list
but can be used as an lvalue.
$hash{@list}
is the same as
$hash{join($;, @list}}
It's a means of doing Hash of Hashes without actually using Hash of Hashes. It's generally unused.
| [reply] [d/l] [select] |
Re: Difference Quantity of two Arrays
by PreferredUserName (Pilgrim) on Jan 02, 2007 at 14:43 UTC
|
sub create_list {
my @skip_dbs = @_;
# declare the hash
my %skippables;
# populate the hash with the skippables
$skippables{$_}++ for @skip_dbs;
my @dbs = qw/fetch forward user smtp/;
# return a list of each element of @dbs
# that isn't in the skippables hash
return grep { ! $skippables{$_} } @dbs;
}
my @list = create_list("user", "smtp");
print "@list";
| [reply] [d/l] |
|
|
# populate the hash with the skippables
$skippables{$_}++ for @skip_dbs;
| [reply] [d/l] [select] |
|
|
It's the increment operator.
When dealing with numbers (or undef),
$a++
means
$a = $a + 1
except it won't issue a warning if $a is undefined.
| [reply] [d/l] [select] |
Re: Difference Quantity of two Arrays
by PreferredUserName (Pilgrim) on Jan 02, 2007 at 14:47 UTC
|
And for the heck of it, here's a minimal-magic version:
sub create_list
{
my @skip_dbs = @_;
# declare the hash
my %skippables;
# populate the hash with the skippables
foreach my $skip_db (@skip_dbs)
{
$skippables{$skip_db} = 1;
}
my @dbs = qw/fetch forward user smtp/;
# create a list of each element of @dbs
# that isn't in the skippables hash
my @good_dbs;
foreach my $db (@dbs)
{
unless (exists $skippables{$db})
{
push @good_dbs, $db
}
}
return @good_dbs;
}
my @list = create_list("user", "smtp");
print "@list";
| [reply] [d/l] |
Re: Difference Quantity of two Arrays
by cdarke (Prior) on Jan 02, 2007 at 14:51 UTC
|
How about using a hash? The main problem here is that any original order will be lost, but maybe that does not matter?
#!/usr/bin/perl -wl
use strict;
sub create_list {
my @skip_dbs = @_;
my %hash;
@hash{qw/fetch forward user smtp/} = undef;
delete @hash{@skip_dbs};
return keys %hash
}
my @list = create_list("user", "smtp");
print "@list";
| [reply] [d/l] |
Re: Difference Quantity of two Arrays
by jettero (Monsignor) on Jan 02, 2007 at 14:40 UTC
|
If the skiplist is small enough, I'd chose something like $skip_rule = join("|", @skip_dbs); $skip_rule = qr{^(?:$skip_rule)$}; and then return grep {$_ !~ $skip_rule} @dbs. If the skip list is huge, that might not be such a good idea.
| [reply] [d/l] [select] |
|
|
qr{...} is quotish so you could do $" = q{|}; $skip_rule = qr{^(?:@skip_dbs)$};, probably localising the change of $" inside a small code block.Cheers, JohnGG
| [reply] [d/l] [select] |
Re: Difference Quantity of two Arrays
by polettix (Vicar) on Jan 02, 2007 at 15:21 UTC
|
How about using the hash for the banned keys? Something along these UNTESTED lines: sub subtract {
my ($whole_ref, $banned_ref) = @_;
my %is_banned = map { $_ => 1 } @$banned_ref;
return grep { ! $is_banned{$_} } @$whole_ref;
}
my @surviving = subtract([qw(fetch forward user smtp)], [qw(user smtp)
+]);
This will also preserve the ordering in the original "whole" array. Note that array references are passed to the subtract() sub, in order to be able to pass two arrays (the first with the "whole" list and the other with the "banned" one).
Flavio
perl -ple'$_=reverse' <<<ti.xittelop@oivalf
Don't fool yourself.
| [reply] [d/l] [select] |
Re: Difference Quantity of two Arrays
by Moron (Curate) on Jan 02, 2007 at 16:31 UTC
|
a grep variant of the same thing my @b1 = (); push @b1, $_, 1 for @b; my %b = @b1;
my @c = grep !$b{$_}, @a;
| [reply] [d/l] |
Re: Difference Quantity of two Arrays
by throop (Chaplain) on Jan 02, 2007 at 15:37 UTC
|
I was surprised that this wasn't in CPAN's List::MoreUtils. Seems like this is a fairly common need.throop | [reply] |
|
|
| [reply] |
|
|
| [reply] [d/l] [select] |
|
|
use strict;
use warnings;
use List::Compare;
my @dbs = qw(fetch forward user smtp);
my @skip_dbs = qw(user smtp);
my $lc = List::Compare->new(\@dbs, \@skip_dbs);
my @list = $lc->get_unique;
print @list;
Cheers,
Brent
| [reply] [d/l] |