Here's another option using smart matching:
use Modern::Perl; my $a = "AB:APPLE:BOY:ZOO:ZOOM"; my $b = "APPLE:ZOO"; my $c = "BOY:GIRL"; say isSubset( $b, $a ); #Returns 1 say !isSubset( $c, $a ); #Returns 1 sub isSubset { my @small = split ':', $_[0]; my @big = split ':', $_[1]; @small ~~ [ grep $_ ~~ @big, @small ]; }
Update: The subroutine below might be more efficient, since it's not building a list (the results are the same):
sub isSubset { my $count = my @small = split ':', $_[0]; my @big = split ':', $_[1]; do { $count-- when @big } for @small; !$count; }
Here's an interesting read: How fast is Perl's smart match operator for searching scalar in an array?.
UpdateUpdate: Ran a benchmark on three subroutines having different set/subset algorithms:
use Modern::Perl; use Benchmark qw(cmpthese); my $a = "AB:APPLE:BOY:ZOO:ZOOM"; my $b = "APPLE:ZOO"; my $c = "BOY:GIRL"; sub isSubset { my @small = split ':', $_[0]; my @big = split ':', $_[1]; @small ~~ [ grep $_ ~~ @big, @small ]; } sub isSubsetSmarter { my $count = my @small = split ':', $_[0]; my @big = split ':', $_[1]; do { $count-- when @big } for @small; !$count; } sub isSubsetHash { my $count = my @small = split ':', $_[0]; my %big; $big{$_} = 1 for split ':', $_[1]; do { $count-- if $big{$_} } for @small; !$count; } cmpthese( -5, { isSubset => sub { isSubset( $b, $a ) }, isSubsetSmarter => sub { isSubsetSmarter( $b, $a ) }, isSubsetHash => sub { say isSubsetHash( $b, $a ) }, } );
Results:
Rate isSubset isSubsetHash isSubsetSmarter isSubset 143452/s -- -15% -54% isSubsetHash 169263/s 18% -- -45% isSubsetSmarter 309705/s 116% 83% --
The original isSubset is the slowest, but isSubsetSmarter is surprisingly the fastest of the crew--at least with these small data sets.
In reply to Re: Computing Subsets
by Kenosis
in thread Computing Subsets
by grandpascorpion
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |