@@ -0,0 +1,21 @@
+/blib/
+/.build/
+_build/
+cover_db/
+inc/
+Build
+!Build/
+Build.bat
+.last_cover_stats
+/Makefile
+/Makefile.old
+/MANIFEST.bak
+/META.yml
+/META.json
+/MYMETA.*
+nytprof.out
+/pm_to_blib
+*.o
+*.bs
+List-Compare-*.tar.gz
+/nytprof/
@@ -1,4 +1,3 @@
-#$Id: Changes 1329 2008-06-07 23:49:51Z jimk $
Revision history for Perl extension List::Compare.
0.04 Sat Jun 8 2002
@@ -36,7 +35,7 @@ Revision history for Perl extension List::Compare.
0.12 Sat Jul 13 2002
- major expansion
- - capability to accelerate processing of comparisons of 2 lists
+ - capability to accelerate processing of comparisons of 2 lists
when only 1 comparison method is expected to be called
- capability to compare more than 2 lists at a time
- introduction of methods including:
@@ -97,7 +96,7 @@ Revision history for Perl extension List::Compare.
0.26 Sun Apr 11 2004
- List::Compare::SeenHash and associated tests deprecated
- - capacity to pass references to seen-hashes to constructor now
+ - capacity to pass references to seen-hashes to constructor now
transferred directly into List::Compare
- corrections to POD
@@ -111,15 +110,15 @@ transferred directly into List::Compare
- further implication of deprecation of List::Compare::SeenHash is that all the code in List::Compare::Base::Regular, L:C:B:Accelerated, L:C:B:Multiple and L:C:B:Multiple::Accelerated is no longer shared between List::Compare and List::Compare::SeenHash and hence can be taken back into List::Compare; thereby eliminating the 'use base' calls from List::Compare.
0.29 Sun May 16 2004
- - implementation of alternative ('Adlerian') interface wherein a single hash reference is passed to constructor or function
+ - implementation of alternative ('Adlerian') interface wherein a single hash reference is passed to constructor or function
0.30 Fri May 21 2004
- documentation corrections only
0.31 Sun Aug 15 2004
- - added methods get_unique_all() and get_complement_all(); added 3335
-tests; repositioned most methods in List::Compare::Base::_Engine to
-List::Compare::Accelerated as they were no longer also being used in
+ - added methods get_unique_all() and get_complement_all(); added 3335
+tests; repositioned most methods in List::Compare::Base::_Engine to
+List::Compare::Accelerated as they were no longer also being used in
List::Compare::Functional; other internal code clean-up
0.32 Sun Sep 18 2005
@@ -148,3 +147,89 @@ List::Compare::Functional; other internal code clean-up
- Tests refined and code refactored so as to achieve 100% subroutine,
statement, branch and condition coverage by test suite as measured by
Devel::Cover. Some cleanup of POD.
+
+0.38 Thu Sep 5 21:09:10 EDT 2013
+ - Update support information; no longer using dedicated mailing list.
+
+0.39 Fri Jul 4 15:38:24 EDT 2014
+ - Repository migrated from Subversion to git. Development repository
+ initiated at https://github.com/jkeenan/list-compare.
+
+0.40 Sat Feb 7 08:39:06 EST 2015
+ - Eliminated three unnecessary hash assignments.
+
+0.41 Sun Feb 8 20:38:46 EST 2015
+ - Revised List::Compare::Functional::_intersection_engine() to eliminate
+ need to call _calculate_xintersection_only() and
+ _calculate_hash_intersection();
+
+0.42 Wed Feb 11 20:57:43 EST 2015
+ - Improve performance of four List::Compare::Functional functions.
+
+ get_nonintersection
+ get_nonintersection_ref
+ get_symmetric_difference
+ get_symmetric_difference_ref
+
+0.43 Thu Feb 12 19:14:35 EST 2015
+ - Improve performance of two List::Compare::Functional functions.
+
+ get_shared
+ get_shared_ref
+
+0.44 Sun Feb 15 14:40:06 EST 2015
+ - Improve performance of complement-related functions in both functional
+ and object-oriented interfaces:
+
+ get_complement
+ get_complement_ref
+ get_complement_all
+
+0.45 Mon Feb 16 16:59:03 EST 2015
+ - Improve performance of unique-related functions in both functional and
+ object-oriented interfaces:
+
+ get_unique
+ get_unique_ref
+ get_unique_all
+
+0.46 Wed Feb 18 19:30:30 EST 2015
+ - Improve performance of List::Compare::Multiple::Accelerated methods:
+
+ get_intersection
+ get_intersection_ref
+ get_shared
+ get_shared_ref
+
+0.47 Sun Feb 22 08:17:54 EST 2015
+ - Improve performance of List::Compare::Multiple::Accelerated methods:
+
+ get_nonintersection
+ get_nonintersection_ref
+ get_symmetric_difference
+ get_symmetric_difference_ref
+
+0.48 Wed Feb 25 17:59:30 EST 2015
+ - Improve performance of is_LdisjointR in List::Compare::Functional and in
+ multiple accelerated mode of List::Compare.
+
+0.49 Sun Mar 8 20:06:20 EDT 2015
+ - Add metadata to Makefile.PL.
+
+0.50 Sat May 9 09:06:41 EDT 2015
+ - Improve performance of is_LsubsetR via patches submitted by Mich Rawson
+ at New York Perl Hackathon (May 2 2015).
+
+0.51 Thu May 14 21:49:00 EDT 2015
+ - Changes to List::Compare::Functional::is_LsubsetR introduced in v0.50
+ found to be buggy. See: https://rt.cpan.org/Ticket/Display.html?id=104452.
+ Pending further investigation, reverted to v0.49 of
+ List::Compare::Base::_Auxiliary; added two test files.
+
+0.52 Thu May 21 21:57:18 EDT 2015
+ - v0.51 changes were not applied to master branch; apply them.
+ Remove two hash-to-hash assignments in List::Compare::Base::_Auxiliary::_subset_subengine.
+
+0.53 Sun Jun 7 10:49:24 MDT 2015
+ - Accept patch submitted by Paulo Custodio reworking, and correcting,
+ changes originally published in 0.50.
@@ -1,4 +1,4 @@
-#$Id: FAQ 1224 2008-04-30 01:53:48Z jimk $
+#$Id$
Q. How can I make comparisons among more than two lists when I don't know in
advance how many lists I'll need to compare?
@@ -1,3 +1,4 @@
+.gitignore
Changes
FAQ
lib/List/Compare.pm
@@ -5,9 +6,8 @@ lib/List/Compare/Base/_Auxiliary.pm
lib/List/Compare/Base/_Engine.pm
lib/List/Compare/Functional.pm
Makefile.PL
-MANIFEST
+MANIFEST This list of files
MANIFEST.SKIP
-META.yml Module meta-data (added by MakeMaker)
README
t/01_oo_lists_dual_reg_sorted.t
t/02_oo_lists_dual_reg_unsorted.t
@@ -57,7 +57,11 @@ t/45_func_hashes_alt_dual_sorted.t
t/46_func_hashes_alt_dual_unsorted.t
t/47_func_hashes_alt_mult_sorted.t
t/48_func_hashes_alt_mult_unsorted.t
+t/49_lc_subset.t
+t/50_lcf_subset.t
t/90_oo_errors.t
t/91_func_errors.t
t/IO/CaptureOutput.pm
t/Test/ListCompareSpecial.pm
+META.yml Module YAML meta-data (added by MakeMaker)
+META.json Module JSON meta-data (added by MakeMaker)
@@ -31,3 +31,7 @@ svndiff/
^init
^results
^htmlify
+.git/
+^MYMETA.*
+nytprof/
+nytprof.out
@@ -0,0 +1,53 @@
+{
+ "abstract" : "Compare elements of two or more lists",
+ "author" : [
+ "James E Keenan (jkeenan@cpan.org)"
+ ],
+ "dynamic_config" : 1,
+ "generated_by" : "ExtUtils::MakeMaker version 7.02, CPAN::Meta::Converter version 2.142690",
+ "license" : [
+ "perl_5"
+ ],
+ "meta-spec" : {
+ "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+ "version" : "2"
+ },
+ "name" : "List-Compare",
+ "no_index" : {
+ "directory" : [
+ "t",
+ "inc"
+ ]
+ },
+ "prereqs" : {
+ "build" : {
+ "requires" : {
+ "ExtUtils::MakeMaker" : "0"
+ }
+ },
+ "configure" : {
+ "requires" : {
+ "ExtUtils::MakeMaker" : "0"
+ }
+ },
+ "test" : {
+ "requires" : {
+ "IO::CaptureOutput" : "0",
+ "Test::Simple" : "0.1"
+ }
+ }
+ },
+ "release_status" : "stable",
+ "resources" : {
+ "bugtracker" : {
+ "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=List-Compare"
+ },
+ "homepage" : "http://thenceforward.net/perl/modules/List-Compare/",
+ "repository" : {
+ "type" : "git",
+ "url" : "https://github.com/jkeenan/list-compare.git",
+ "web" : "https://github.com/jkeenan/list-compare"
+ }
+ },
+ "version" : "0.53"
+}
@@ -1,14 +1,26 @@
---- #YAML:1.0
-name: List-Compare
-version: 0.37
-abstract: Compare elements of two or more lists
-license: ~
-author:
- - James E Keenan (jkeenan@cpan.org)
-generated_by: ExtUtils::MakeMaker version 6.42
-distribution_type: module
-requires:
- Test::Simple: 0.1
+---
+abstract: 'Compare elements of two or more lists'
+author:
+ - 'James E Keenan (jkeenan@cpan.org)'
+build_requires:
+ ExtUtils::MakeMaker: '0'
+ IO::CaptureOutput: '0'
+ Test::Simple: '0.1'
+configure_requires:
+ ExtUtils::MakeMaker: '0'
+dynamic_config: 1
+generated_by: 'ExtUtils::MakeMaker version 7.02, CPAN::Meta::Converter version 2.142690'
+license: perl
meta-spec:
- url: http://module-build.sourceforge.net/META-spec-v1.3.html
- version: 1.3
+ url: http://module-build.sourceforge.net/META-spec-v1.4.html
+ version: '1.4'
+name: List-Compare
+no_index:
+ directory:
+ - t
+ - inc
+resources:
+ bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=List-Compare
+ homepage: http://thenceforward.net/perl/modules/List-Compare/
+ repository: https://github.com/jkeenan/list-compare.git
+version: '0.53'
@@ -1,10 +1,31 @@
-#$Id: Makefile.PL 1224 2008-04-30 01:53:48Z jimk $
use ExtUtils::MakeMaker;
require 5.006;
+
+my $mm_ver = ExtUtils::MakeMaker->VERSION;
+
WriteMakefile(
- NAME => 'List::Compare',
+ NAME => 'List::Compare',
AUTHOR => 'James E Keenan (jkeenan@cpan.org)',
- VERSION_FROM => 'lib/List/Compare.pm',
- ABSTRACT_FROM => 'lib/List/Compare.pm',
- PREREQ_PM => { Test::Simple => 0.10 },
+ VERSION_FROM => 'lib/List/Compare.pm',
+ ABSTRACT_FROM => 'lib/List/Compare.pm',
+ ( $mm_ver < 6.63_03 ? 'BUILD_REQUIRES' : 'TEST_REQUIRES' ) => {
+ 'IO::CaptureOutput' => 0,
+ 'Test::Simple' => 0.10,
+ },
+ LICENSE => "perl",
+ ($mm_ver < 6.46 ? () : (META_MERGE => {
+ 'meta-spec' => { version => 2 },
+ dynamic_config => 1,
+ resources => {
+ homepage => 'http://thenceforward.net/perl/modules/List-Compare/',
+ repository => {
+ url => 'https://github.com/jkeenan/list-compare.git',
+ web => 'https://github.com/jkeenan/list-compare',
+ type => 'git',
+ },
+ bugtracker => {
+ web => 'https://rt.cpan.org/Public/Dist/Display.html?Name=List-Compare',
+ },
+ },
+ })),
);
@@ -1,80 +1,79 @@
-#$Id: README 1329 2008-06-07 23:49:51Z jimk $
List::Compare - Compare elements of two or more lists
-This document refers to version 0.37 of List::Compare. This version was
-released June 07, 2008.
+This document refers to version 0.53 of List::Compare. This version was
+released June 07 2015.
-To install this module on your system, place the tarball archive file in a
+To install this module on your system, place the tarball archive file in a
temporary directory and call the following:
-% gunzip List-Compare-0.37.tar.gz
-% tar xf List-Compare-0.37.tar
-% cd List-Compare-0.37
+% gunzip List-Compare-0.53.tar.gz
+% tar xf List-Compare-0.53.tar
+% cd List-Compare-0.53
% perl Makefile.PL
% make
% make test
% make install
-If during installation you wish to view more information on test results,
+If during installation you wish to view more information on test results,
substitute the fllowing for the sixth line in the sequence of commands
above:
% make test TEST=VERBOSE
-If you are installing this module over any earlier version, you may
-substitute the following for the last line in the sequence of commands
+If you are installing this module over any earlier version, you may
+substitute the following for the last line in the sequence of commands
above:
% make install UNINST=1
-If you are installing this module on a Win32 system with 'nmake',
+If you are installing this module on a Win32 system with 'nmake',
substitute 'nmake' for 'make' in the sequence of commands above.
-The author has found that trying to install this distribution with
-(a) older (pre-6.16) versions of ExtUtils::MakeMaker, (b) on older
-versions of Perl (e.g., 5.6.0), and (c) on older Linux distributions
-(e.g., RedHat Linux 7.3) can result in a situation where the module's
-Plain Old Documentation, when transformed into manual pages, is not
-automatically placed in the optimal location for reading thru 'man'
-and 'info' (even though it reads perfectly through 'perldoc'). If you
-experience this problem, issue the following at the command line
-(adapted from a suggestion by Michael Schwern on the module-authors
+The author has found that trying to install this distribution with
+(a) older (pre-6.16) versions of ExtUtils::MakeMaker, (b) on older
+versions of Perl (e.g., 5.6.0), and (c) on older Linux distributions
+(e.g., RedHat Linux 7.3) can result in a situation where the module's
+Plain Old Documentation, when transformed into manual pages, is not
+automatically placed in the optimal location for reading thru 'man'
+and 'info' (even though it reads perfectly through 'perldoc'). If you
+experience this problem, issue the following at the command line
+(adapted from a suggestion by Michael Schwern on the module-authors
mailing list):
% perl Makefile.PL INSTALLSITEMAN3DIR=/usr/share/man/man3
-List::Compare uses the Carp module which is part of the standard Perl
-distribution. Other than that, there are no module dependencies in
+List::Compare uses the Carp module which is part of the standard Perl
+distribution. Other than that, there are no module dependencies in
this version of List::Compare.
-Certain methods in this version of List::Compare are included solely
-for backwards compatibility with earlier versions and are deprecated.
-When called, they print warning messages via Carp. In earlier versions
-of List::Compare these warning messages would appear when you called
-'make test' as part of the installation process. This was harmless
+Certain methods in this version of List::Compare are included solely
+for backwards compatibility with earlier versions and are deprecated.
+When called, they print warning messages via Carp. In earlier versions
+of List::Compare these warning messages would appear when you called
+'make test' as part of the installation process. This was harmless
but annoying and has been fixed.
-Beginning with version 0.25 in April 2004, there is a modification to the
-interface of two methods/functions: are_members_which() and
-are_members_any(). Whereas previously the strings to be tested could be
-passed to the subroutine either as a flat list or via a reference to an
-anonymous array, now those items must be passed via reference to an
+Beginning with version 0.25 in April 2004, there is a modification to the
+interface of two methods/functions: are_members_which() and
+are_members_any(). Whereas previously the strings to be tested could be
+passed to the subroutine either as a flat list or via a reference to an
+anonymous array, now those items must be passed via reference to an
anonymous array.
-Beginning with version 0.26 in April 2004, the functionality previously
-found in List::Compare::SeenHash has been incorporated directly into
-List::Compare. Hence, List::Compare::SeenHash and the test suite files
-associated with it have been deprecated and are no longer included in the
-CPAN distribution. Please see the List::Compare documentation for
+Beginning with version 0.26 in April 2004, the functionality previously
+found in List::Compare::SeenHash has been incorporated directly into
+List::Compare. Hence, List::Compare::SeenHash and the test suite files
+associated with it have been deprecated and are no longer included in the
+CPAN distribution. Please see the List::Compare documentation for
further details.
-In sending e-mail to the author, please put "List::Compare" or
+In sending e-mail to the author, please put "List::Compare" or
"List-Compare" in the subject line.
Author: James E. Keenan (jkeenan@cpan.org).
Originally created May 20, 2002.
-Copyright (c) 2002-08 James E. Keenan. United States. All rights reserved.
+Copyright (c) 2002-15 James E. Keenan. United States. All rights reserved.
This is free software and may be distributed under the same terms as Perl
itself.
@@ -1,74 +1,69 @@
package List::Compare::Base::_Auxiliary;
-#$Id: _Auxiliary.pm 1329 2008-06-07 23:49:51Z jimk $
-$VERSION = 0.37;
+$VERSION = 0.53;
use Carp;
@ISA = qw(Exporter);
@EXPORT_OK = qw|
_validate_2_seenhashes
_validate_seen_hash
_validate_multiple_seenhashes
- _calculate_union_xintersection_only
- _calculate_seen_xintersection_only
+ _calculate_array_seen_only
_calculate_seen_only
- _calculate_xintersection_only
+ _calculate_intermediate
_calculate_union_only
_calculate_union_seen_only
- _calculate_hash_intersection
- _calculate_hash_shared
+ _calculate_sharedref
_subset_subengine
- _chart_engine_regular
+ _chart_engine_regular
_chart_engine_multiple
_equivalent_subengine
_index_message1
_index_message2
_index_message3
_index_message4
- _prepare_listrefs
- _subset_engine_multaccel
+ _prepare_listrefs
+ _subset_engine_multaccel
_calc_seen
_calc_seen1
- _equiv_engine
- _argument_checker_0
- _argument_checker
- _argument_checker_1
- _argument_checker_2
- _argument_checker_3
- _argument_checker_3a
+ _equiv_engine
+ _argument_checker_0
+ _argument_checker
+ _argument_checker_1
+ _argument_checker_2
+ _argument_checker_3
+ _argument_checker_3a
_argument_checker_4
- _alt_construct_tester
- _alt_construct_tester_1
- _alt_construct_tester_2
- _alt_construct_tester_3
- _alt_construct_tester_4
- _alt_construct_tester_5
+ _alt_construct_tester
+ _alt_construct_tester_1
+ _alt_construct_tester_2
+ _alt_construct_tester_3
+ _alt_construct_tester_4
+ _alt_construct_tester_5
|;
%EXPORT_TAGS = (
calculate => [ qw(
- _calculate_union_xintersection_only
- _calculate_seen_xintersection_only
+ _calculate_array_seen_only
_calculate_seen_only
- _calculate_xintersection_only
+ _calculate_intermediate
_calculate_union_only
_calculate_union_seen_only
- _calculate_hash_intersection
- _calculate_hash_shared
+ _calculate_sharedref
) ],
checker => [ qw(
- _argument_checker_0
- _argument_checker
- _argument_checker_1
- _argument_checker_2
- _argument_checker_3
- _argument_checker_3a
+ _argument_checker_0
+ _argument_checker
+ _argument_checker_1
+ _argument_checker_2
+ _argument_checker_3
+ _argument_checker_3a
_argument_checker_4
) ],
tester => [ qw(
- _alt_construct_tester
- _alt_construct_tester_1
- _alt_construct_tester_2
- _alt_construct_tester_3
- _alt_construct_tester_4
- _alt_construct_tester_5
+ _alt_construct_tester
+ _alt_construct_tester_1
+ _alt_construct_tester_2
+ _alt_construct_tester_3
+ _alt_construct_tester_4
+ _alt_construct_tester_5
) ],
);
use strict;
@@ -86,7 +81,7 @@ sub _validate_2_seenhashes {
} else {
$badentriesL{$_} = ${$refL}{$_};
}
- }
+ }
foreach (keys %$refR) {
if (${$refR}{$_} =~ /^\d+$/ and ${$refR}{$_} > 0) {
$seenR{$_} = ${$refR}{$_};
@@ -100,12 +95,12 @@ sub _validate_2_seenhashes {
$msg .= " These elements have invalid values:\n";
if (keys %badentriesL) {
$msg .= " First hash in arguments:\n";
- $msg .= " Key: $_\tValue: $badentriesL{$_}\n"
+ $msg .= " Key: $_\tValue: $badentriesL{$_}\n"
foreach (sort keys %badentriesL);
- }
+ }
if (keys %badentriesR) {
$msg .= " Second hash in arguments:\n";
- $msg .= " Key: $_\tValue: $badentriesR{$_}\n"
+ $msg .= " Key: $_\tValue: $badentriesR{$_}\n"
foreach (sort keys %badentriesR);
}
$msg .= "Correct invalid values before proceeding";
@@ -117,15 +112,15 @@ sub _validate_2_seenhashes {
sub _validate_seen_hash {
if (@_ > 2) {
_validate_multiple_seenhashes( [@_] );
- } else {
+ } else {
my ($l, $r) = @_;
my (%badentriesL, %badentriesR);
foreach (keys %$l) {
- $badentriesL{$_} = ${$l}{$_}
+ $badentriesL{$_} = ${$l}{$_}
unless (${$l}{$_} =~ /^\d+$/ and ${$l}{$_} > 0);
- }
+ }
foreach (keys %$r) {
- $badentriesR{$_} = ${$r}{$_}
+ $badentriesR{$_} = ${$r}{$_}
unless (${$r}{$_} =~ /^\d+$/ and ${$r}{$_} > 0);
}
my $msg = q{};
@@ -134,12 +129,12 @@ sub _validate_seen_hash {
$msg .= " These elements have invalid values:\n";
if (keys %badentriesL) {
$msg .= " First hash in arguments:\n";
- $msg .= " Key: $_\tValue: $badentriesL{$_}\n"
+ $msg .= " Key: $_\tValue: $badentriesL{$_}\n"
foreach (sort keys %badentriesL);
- }
+ }
if (keys %badentriesR) {
$msg .= " Second hash in arguments:\n";
- $msg .= " Key: $_\tValue: $badentriesR{$_}\n"
+ $msg .= " Key: $_\tValue: $badentriesR{$_}\n"
foreach (sort keys %badentriesR);
}
$msg .= "Correct invalid values before proceeding";
@@ -150,26 +145,22 @@ sub _validate_seen_hash {
sub _validate_multiple_seenhashes {
my $hashrefsref = shift;
- my @hashrefs = @{$hashrefsref};
- my (%badentries, $badentriesflag);
- for (my $i = 0; $i <= $#hashrefs; $i++) {
- my %seenhash = %{$hashrefs[$i]};
- foreach (keys %seenhash) {
- unless ($seenhash{$_} =~ /^\d+$/ and $seenhash{$_} > 0) {
- $badentries{$i}{$_} = $seenhash{$_};
- $badentriesflag++;
+ my (%badentries);
+ for (my $i = 0; $i <= $#{$hashrefsref}; $i++) {
+ foreach my $k (keys %{$hashrefsref->[$i]}) {
+ unless ($hashrefsref->[$i]->{$k} =~ /^\d+$/ and $hashrefsref->[$i]->{$k} > 0) {
+ $badentries{$i}{$k} = $hashrefsref->[$i]->{$k};
}
}
}
my $msg = q{};
- if ($badentriesflag) {
+ if (scalar(keys %badentries)) {
$msg .= "\nValues in a 'seen-hash' must be positive integers.\n";
$msg .= " These elements have invalid values:\n\n";
- foreach (sort keys %badentries) {
- $msg .= " Hash $_:\n";
- my %pairs = %{$badentries{$_}};
- foreach my $val (sort keys %pairs) {
- $msg .= " Bad key-value pair: $val\t$pairs{$val}\n";
+ foreach my $b (sort keys %badentries) {
+ $msg .= " Hash $b:\n";
+ foreach my $val (sort keys %{$badentries{$b}}) {
+ $msg .= " Bad key-value pair: $val\t$badentries{$b}->{$val}\n";
}
}
$msg .= "Correct invalid values before proceeding";
@@ -186,49 +177,17 @@ sub _list_builder {
}
}
-sub _calculate_union_xintersection_only {
+sub _calculate_array_seen_only {
my $aref = shift;
- my (%union, %xintersection);
+ my (@seen);
for (my $i = 0; $i <= $#{$aref}; $i++) {
my %seenthis = ();
- foreach my $h ( _list_builder($aref, $i) ) {
- $seenthis{$h}++;
- $union{$h}++;
- }
- for (my $j = $i+1; $j <=$#{$aref}; $j++) {
- my %seenthat = ();
- my %seenintersect = ();
- my $ilabel = $i . '_' . $j;
- $seenthat{$_}++ foreach ( _list_builder($aref, $j) );
- foreach my $k (keys %seenthat) {
- $seenintersect{$k}++ if (exists $seenthis{$k});
- }
- $xintersection{$ilabel} = \%seenintersect;
- }
- }
- return (\%union, \%xintersection);
-}
-
-sub _calculate_seen_xintersection_only {
- my $aref = shift;
- my (%xintersection, %seen);
- for (my $i = 0; $i <= $#{$aref}; $i++) {
- my %seenthis = ();
- foreach my $h ( _list_builder($aref, $i) ) {
- $seenthis{$h}++;
- }
- $seen{$i} = \%seenthis;
- for (my $j = $i+1; $j <=$#{$aref}; $j++) {
- my (%seenthat, %seenintersect);
- my $ilabel = $i . '_' . $j;
- $seenthat{$_}++ foreach ( _list_builder($aref, $j) );
- foreach (keys %seenthat) {
- $seenintersect{$_}++ if (exists $seenthis{$_});
- }
- $xintersection{$ilabel} = \%seenintersect;
+ foreach my $el ( _list_builder($aref, $i) ) {
+ $seenthis{$el}++;
}
+ push @seen, \%seenthis;
}
- return (\%seen, \%xintersection);
+ return \@seen;
}
sub _calculate_seen_only {
@@ -244,25 +203,17 @@ sub _calculate_seen_only {
return \%seen;
}
-sub _calculate_xintersection_only {
+sub _calculate_intermediate {
my $aref = shift;
- my (%xintersection);
- for (my $i = 0; $i <= $#{$aref}; $i++) {
- my %seenthis = ();
- foreach my $h ( _list_builder($aref, $i) ) {
- $seenthis{$h}++;
- }
- for (my $j = $i+1; $j <=$#{$aref}; $j++) {
- my (%seenthat, %seenintersect);
- my $ilabel = $i . '_' . $j;
- $seenthat{$_}++ foreach ( _list_builder($aref, $j) );
- foreach (keys %seenthat) {
- $seenintersect{$_}++ if (exists $seenthis{$_});
- }
- $xintersection{$ilabel} = \%seenintersect;
- }
+ my $aseenref = _calculate_array_seen_only($aref);
+ my @vals = sort { scalar(keys(%{$a})) <=> scalar(keys(%{$b})) } @{$aseenref};
+ my %intermediate = map { $_ => 1 } keys %{$vals[0]};
+ for my $l ( 1..$#vals ) {
+ %intermediate = map { $_ => 1 }
+ grep { exists $intermediate{$_} }
+ keys %{$vals[$l]};
}
- return \%xintersection;
+ return \%intermediate;
}
sub _calculate_union_only {
@@ -290,48 +241,62 @@ sub _calculate_union_seen_only {
return (\%union, \%seen);
}
-sub _calculate_hash_intersection {
- my $xintersectionref = shift;
- my @xkeys = keys %{$xintersectionref};
- my %intersection = %{${$xintersectionref}{$xkeys[0]}};
- for (my $m = 1; $m <= $#xkeys; $m++) {
- my %compare = %{${$xintersectionref}{$xkeys[$m]}};
- my %result = ();
- foreach (keys %compare) {
- $result{$_}++ if (exists $intersection{$_});
- }
- %intersection = %result;
+sub _calculate_sharedref {
+ my $seenrefsref = shift;
+
+ my %intermediate = ();
+ for my $href (@{$seenrefsref}) {
+ my %this = map { $_ => 1 } keys(%{$href});
+ for my $k (keys %this) {;
+ $intermediate{$k}++;
+ };
}
- return \%intersection;
-}
-sub _calculate_hash_shared {
- my $xintersectionref = shift;
- my (%shared);
- foreach my $q (keys %{$xintersectionref}) {
- $shared{$_}++ foreach (keys %{${$xintersectionref}{$q}});
+ my $sharedref;
+ for my $k (keys %intermediate) {
+ $sharedref->{$k}++ if $intermediate{$k} > 1;
}
- return \%shared;
+ return $sharedref;
+}
+
+sub _is_list_subset {
+ my ( $subset, $superset ) = @_;
+ # return false if the superset value is false
+ # for any subset value.
+ # note that this does *not* validate overlap of
+ # the keys; it validates the truth of supserset
+ # values.
+ $superset->{ $_ } or return 0 for keys %$subset;
+ return 1;
}
sub _subset_subengine {
my $aref = shift;
my (@xsubset);
- my $seenref = _calculate_seen_only($aref);
- my %seen = %{$seenref};
+ my %seen = %{_calculate_seen_only($aref)};
foreach my $i (keys %seen) {
- my %tempi = %{$seen{$i}};
foreach my $j (keys %seen) {
- my %tempj = %{$seen{$j}};
- $xsubset[$i][$j] = 1;
- foreach my $k (keys %tempi) {
- $xsubset[$i][$j] = 0 if (! $tempj{$k});
+ if ( $i eq $j ) {
+ $xsubset[$i][$j] = 1;
+ }
+ elsif ( $i gt $j ) {
+ if ( scalar(keys %{ $seen{$i} }) == scalar(keys %{ $seen{$j} }) ){
+ $xsubset[$i][$j] = _is_list_subset($seen{$i}, $seen{$j});
+ $xsubset[$j][$i] = $xsubset[$i][$j];
+ }
+ elsif ( scalar(keys %{ $seen{$i} }) < scalar(keys %{ $seen{$j} }) ){
+ $xsubset[$i][$j] = _is_list_subset($seen{$i}, $seen{$j});
+ $xsubset[$j][$i] = 0;
+ }
+ elsif ( scalar(keys %{ $seen{$i} }) > scalar(keys %{ $seen{$j} }) ){
+ $xsubset[$j][$i] = _is_list_subset($seen{$j}, $seen{$i});
+ $xsubset[$i][$j] = 0;
+ }
}
}
}
return \@xsubset;
}
-
sub _chart_engine_regular {
my $aref = shift;
my @sub_or_eqv = @$aref;
@@ -377,8 +342,7 @@ sub _chart_engine_multiple {
sub _equivalent_subengine {
my $aref = shift;
- my $xsubsetref = _subset_subengine($aref);
- my @xsubset = @{$xsubsetref};
+ my @xsubset = @{_subset_subengine($aref)};
my (@xequivalent);
for (my $f = 0; $f <= $#xsubset; $f++) {
for (my $g = 0; $g <= $#xsubset; $g++) {
@@ -395,7 +359,7 @@ sub _index_message1 {
my $method = (caller(1))[3];
croak "Argument to method $method must be the array index of the target list \n in list of arrays passed as arguments to the constructor: $!"
unless (
- $index =~ /^\d+$/
+ $index =~ /^\d+$/
and $index <= ${$dataref}{'maxindex'}
);
}
@@ -414,7 +378,7 @@ sub _index_message2 {
foreach ($index_left, $index_right) {
croak "Each argument to method $method must be a valid array index for the target list \n in list of arrays passed as arguments to the constructor: $!"
unless (
- $_ =~ /^\d+$/
+ $_ =~ /^\d+$/
and $_ <= ${$dataref}{'maxindex'}
);
}
@@ -427,7 +391,7 @@ sub _index_message3 {
my $method = (caller(1))[3];
croak "Argument to method $method must be the array index of the target list \n in list of arrays passed as arguments to the constructor: $!"
unless (
- $index =~ /^\d+$/
+ $index =~ /^\d+$/
and $index <= $maxindex
);
}
@@ -446,7 +410,7 @@ sub _index_message4 {
foreach ($index_left, $index_right) {
croak "Each argument to method $method must be a valid array index for the target list \n in list of arrays passed as arguments to the constructor: $!"
unless (
- $_ =~ /^\d+$/
+ $_ =~ /^\d+$/
and $_ <= $maxindex
);
}
@@ -481,7 +445,7 @@ sub _calc_seen {
my (%seenL, %seenR);
foreach (@$refL) { $seenL{$_}++ }
foreach (@$refR) { $seenR{$_}++ }
- return (\%seenL, \%seenR);
+ return (\%seenL, \%seenR);
} else {
return ($refL, $refR);
}
@@ -491,7 +455,7 @@ sub _equiv_engine {
my ($hrefL, $hrefR) = @_;
my (%intersection, %Lonly, %Ronly, %LorRonly);
my $LequivalentR_status = 0;
-
+
foreach (keys %{$hrefL}) {
exists ${$hrefR}{$_} ? $intersection{$_}++ : $Lonly{$_}++;
}
@@ -548,9 +512,9 @@ sub _argument_checker_2 {
# _argument_checker_3 is currently set-up to handle either 1 or 2 arguments
# in get_unique and get_complement
-# The first argument is an arrayref holding refs to lists ('unsorted' has been
+# The first argument is an arrayref holding refs to lists ('unsorted' has been
# stripped off).
-# The second argument is an arrayref holding a single item (index number of
+# The second argument is an arrayref holding a single item (index number of
# item being tested)
# Note: Currently we're only checking for the quantity of arguments -- not
# their types. This should be fixed.
@@ -585,7 +549,7 @@ sub _argument_checker_4 {
if (@{$args[1]} == 2) {
my $last_index = $#{$args[0]};
foreach my $i (@{$args[1]}) {
- croak "No element in index position $i in list of list references passed as first argument to function: $!"
+ croak "No element in index position $i in list of list references passed as first argument to function: $!"
unless ($i =~ /^\d+$/ and $i <= $last_index);
}
return (_argument_checker($args[0]), $args[1]);
@@ -600,9 +564,9 @@ sub _argument_checker_4 {
sub _calc_seen1 {
my @listrefs = @_;
# _calc_seen1() is applied after _argument_checker(), which checks to make
- # sure that the references in its output are either all arrayrefs
+ # sure that the references in its output are either all arrayrefs
# or all seenhashrefs
- # hence, _calc_seen1 only needs to determine whether it's dealing with
+ # hence, _calc_seen1 only needs to determine whether it's dealing with
# arrayrefs or seenhashrefs, then, if arrayrefs, calculate seenhashes
if (ref($listrefs[0]) eq 'ARRAY') {
my (@seenrefs);
@@ -619,7 +583,7 @@ sub _calc_seen1 {
}
}
-# _alt_construct_tester prepares for _argument_checker in
+# _alt_construct_tester prepares for _argument_checker in
# get_union get_intersection get_symmetric_difference get_shared get_nonintersection
sub _alt_construct_tester {
my @args = @_;
@@ -632,9 +596,9 @@ sub _alt_construct_tester {
$argref = ${$hashref}{'lists'};
$unsorted = ${$hashref}{'unsorted'} ? 1 : '';
} else {
- $unsorted = shift(@args)
+ $unsorted = shift(@args)
if ($args[0] eq '-u' or $args[0] eq '--unsorted');
- $argref = shift(@args);
+ $argref = shift(@args);
}
return ($argref, $unsorted);
}
@@ -655,7 +619,7 @@ sub _alt_construct_tester_1 {
@returns = ( ${$hashref}{'lists'}, [${$hashref}{'item'}] );
$argref = \@returns;
} else {
- $argref = \@args;
+ $argref = \@args;
}
return $argref;
}
@@ -679,7 +643,7 @@ sub _alt_construct_tester_2 {
}
# _alt_construct_tester_3 prepares for _argument_checker_3 in
-# get_unique get_complement
+# get_unique get_complement
sub _alt_construct_tester_3 {
my @args = @_;
my ($argref, $unsorted);
@@ -696,7 +660,7 @@ sub _alt_construct_tester_3 {
$unsorted = ${$hashref}{'unsorted'} ? 1 : '';
} else {
$unsorted = shift(@args) if ($args[0] eq '-u' or $args[0] eq '--unsorted');
- $argref = \@args;
+ $argref = \@args;
}
return ($argref, $unsorted);
}
@@ -717,7 +681,7 @@ sub _alt_construct_tester_4 {
: (${$hashref}{'lists'});
$argref = \@returns;
} else {
- $argref = \@args;
+ $argref = \@args;
}
return $argref;
}
@@ -735,7 +699,7 @@ sub _alt_construct_tester_5 {
and (ref(${$hashref}{'lists'}) eq 'ARRAY') );
$argref = ${$hashref}{'lists'};
} else {
- $argref = shift(@args);
+ $argref = shift(@args);
}
} else {
croak "Subroutine call requires exactly 1 reference as argument: $!";
@@ -753,23 +717,23 @@ List::Compare::Base::_Auxiliary - Internal use only
=head1 VERSION
-This document refers to version 0.37 of List::Compare::Base::_Auxiliary.
-This version was released June 07, 2008.
+This document refers to version 0.53 of List::Compare::Base::_Auxiliary.
+This version was released June 07 2015.
=head1 SYNOPSIS
-This module contains subroutines used within List::Compare and
+This module contains subroutines used within List::Compare and
List::Compare::Functional. They are not intended to be publicly callable.
=head1 AUTHOR
-James E. Keenan (jkeenan@cpan.org). When sending correspondence, please
+James E. Keenan (jkeenan@cpan.org). When sending correspondence, please
include 'List::Compare' or 'List-Compare' in your subject line.
-Creation date: May 20, 2002. Last modification date: June 07, 2008.
-Copyright (c) 2002-08 James E. Keenan. United States. All rights reserved.
+Creation date: May 20, 2002. Last modification date: February 25 2015.
+Copyright (c) 2002-15 James E. Keenan. United States. All rights reserved.
This is free software and may be distributed under the same terms as Perl
itself.
-=cut
+=cut
@@ -1,14 +1,12 @@
package List::Compare::Base::_Engine;
-#$Id: _Engine.pm 1329 2008-06-07 23:49:51Z jimk $
-$VERSION = 0.37;
-# Holds subroutines used within
+$VERSION = 0.53;
+# Holds subroutines used within
# List::Compare::Base::Accelerated and List::Compare::Functional
-# As of: 09/18/2005
use Carp;
use List::Compare::Base::_Auxiliary qw(
- _equiv_engine
- _calculate_seen_xintersection_only
+ _equiv_engine
_calculate_union_seen_only
+ _calculate_seen_only
);
@ISA = qw(Exporter);
@EXPORT_OK = qw|
@@ -20,52 +18,41 @@ local $^W = 1;
sub _unique_all_engine {
my $aref = shift;
- my ($seenref, $xintersectionref) =
- _calculate_seen_xintersection_only($aref);
- my %seen = %{$seenref};
- my %xintersection = %{$xintersectionref};
-
- # Calculate @xunique
- # Inputs: $aref %seen %xintersection
- my (@xunique);
- for (my $i = 0; $i <= $#{$aref}; $i++) {
- my %seenthis = %{$seen{$i}};
- my (@uniquethis, %deductions, %alldeductions);
- # Get those elements of %xintersection which we'll need
- # to subtract from %seenthis
- foreach (keys %xintersection) {
- my ($left, $right) = split /_/, $_;
- if ($left == $i || $right == $i) {
- $deductions{$_} = $xintersection{$_};
- }
- }
- foreach my $ded (keys %deductions) {
- foreach (keys %{$deductions{$ded}}) {
- $alldeductions{$_}++;
+ my $seenref = _calculate_seen_only($aref);
+
+ my @all_uniques = ();
+ for my $i (sort {$a <=> $b} keys %{$seenref}) {
+ my %seen_in_all_others = ();
+ for my $j (keys %{$seenref}) {
+ unless ($i == $j) {
+ for my $k (keys %{$seenref->{$j}}) {
+ $seen_in_all_others{$k}++;
+ }
}
+
}
- foreach (keys %seenthis) {
- push(@uniquethis, $_) unless ($alldeductions{$_});
+ my @these_uniques = ();
+ for my $l (keys %{$seenref->{$i}}) {
+ push @these_uniques, $l
+ unless $seen_in_all_others{$l};
}
- $xunique[$i] = \@uniquethis;
+ $all_uniques[$i] = \@these_uniques;
}
- return \@xunique;
+ return \@all_uniques;
}
sub _complement_all_engine {
my ($aref, $unsortflag) = @_;
my ($unionref, $seenref) = _calculate_union_seen_only($aref);
- my %seen = %{$seenref};
my @union = $unsortflag ? keys %{$unionref} : sort(keys %{$unionref});
# Calculate @xcomplement
# Inputs: $aref @union %seen
my (@xcomplement);
for (my $i = 0; $i <= $#{$aref}; $i++) {
- my %seenthis = %{$seen{$i}};
my @complementthis = ();
- foreach (@union) {
- push(@complementthis, $_) unless (exists $seenthis{$_});
+ foreach my $el (@union) {
+ push(@complementthis, $el) unless (exists $seenref->{$i}->{$el});
}
$xcomplement[$i] = \@complementthis;
}
@@ -83,23 +70,23 @@ List::Compare::Base::_Engine - Internal use only
=head1 VERSION
-This document refers to version 0.37 of List::Compare::Base::_Engine.
-This version was released June 07, 2008.
+This document refers to version 0.53 of List::Compare::Base::_Engine.
+This version was released June 07 2015.
=head1 SYNOPSIS
-This module contains subroutines used within List::Compare and
+This module contains subroutines used within List::Compare and
List::Compare::Functional. They are not intended to be publicly callable.
=head1 AUTHOR
-James E. Keenan (jkeenan@cpan.org). When sending correspondence, please
+James E. Keenan (jkeenan@cpan.org). When sending correspondence, please
include 'List::Compare' or 'List-Compare' in your subject line.
-Creation date: May 20, 2002. Last modification date: June 07, 2008.
-Copyright (c) 2002-04 James E. Keenan. United States. All rights reserved.
+Creation date: May 20, 2002. Last modification date: June 07 2015.
+Copyright (c) 2002-15 James E. Keenan. United States. All rights reserved.
This is free software and may be distributed under the same terms as Perl
itself.
-=cut
+=cut
@@ -1,6 +1,5 @@
package List::Compare::Functional;
-#$Id: Functional.pm 1329 2008-06-07 23:49:51Z jimk $
-$VERSION = 0.37;
+$VERSION = 0.53;
@ISA = qw(Exporter);
@EXPORT_OK = qw|
get_intersection
@@ -101,8 +100,8 @@ use List::Compare::Base::_Auxiliary qw(
_calc_seen1
);
use List::Compare::Base::_Auxiliary qw(:calculate :checker :tester);
-use List::Compare::Base::_Engine qw(
- _unique_all_engine
+use List::Compare::Base::_Engine qw(
+ _unique_all_engine
_complement_all_engine
);
@@ -113,7 +112,7 @@ sub get_union {
sub get_union_ref {
my ($argref, $unsorted) = _alt_construct_tester(@_);
- $unsorted
+ $unsorted
? return _union_engine(_argument_checker($argref))
: return [ sort @{_union_engine(_argument_checker($argref))} ];
}
@@ -130,16 +129,22 @@ sub get_intersection {
sub get_intersection_ref {
my ($argref, $unsorted) = _alt_construct_tester(@_);
- $unsorted
+ $unsorted
? return _intersection_engine(_argument_checker($argref))
: return [ sort @{_intersection_engine(_argument_checker($argref))} ];
}
sub _intersection_engine {
my $seenrefsref = _calc_seen1(@_);
- my $xintersectionref = _calculate_xintersection_only($seenrefsref);
- my $intersectionref = _calculate_hash_intersection($xintersectionref);
- return [ keys %{$intersectionref} ];
+ my @vals = sort { scalar(keys(%{$a})) <=> scalar(keys(%{$b})) }
+ @{$seenrefsref};
+ my %intersection = map { $_ => 1 } keys %{$vals[0]};
+ for my $l ( 1..$#vals ) {
+ %intersection = map { $_ => 1 }
+ grep { exists $intersection{$_} }
+ keys %{$vals[$l]};
+ }
+ return [ keys %intersection ];
}
sub get_unique {
@@ -161,37 +166,27 @@ sub get_unique_all {
}
sub _unique_engine {
- my $tested = pop(@_);
- my $seenrefsref = _calc_seen1(@_);
- my ($seenref, $xintersectionref) =
- _calculate_seen_xintersection_only($seenrefsref);
- my %seen = %{$seenref};
- my %xintersection = %{$xintersectionref};
-
- # Calculate %xunique
- my (%xunique);
- for (my $i = 0; $i <= $#{$seenrefsref}; $i++) {
- my %seenthis = %{$seen{$i}};
- my (@uniquethis, %deductions, %alldeductions);
- # Get those elements of %xintersection which we'll need
- # to subtract from %seenthis
- foreach (keys %xintersection) {
- my ($left, $right) = split /_/, $_;
- if ($left == $i || $right == $i) {
- $deductions{$_} = $xintersection{$_};
+ my $index = pop(@_);
+ my $seenref = _calculate_seen_only(_calc_seen1(@_));
+
+ my %seen_in_all_others = ();
+ my @seenthis = ();
+ for my $i (keys %{$seenref}) {
+ unless ($i == $index) {
+ for my $k (keys %{$seenref->{$i}}) {
+ $seen_in_all_others{$k}++;
}
}
- foreach my $ded (keys %deductions) {
- foreach (keys %{$deductions{$ded}}) {
- $alldeductions{$_}++;
- }
+ else {
+ @seenthis = keys %{$seenref->{$index}};
}
- foreach (keys %seenthis) {
- push(@uniquethis, $_) unless ($alldeductions{$_});
- }
- $xunique{$i} = \@uniquethis;
}
- return [ @{$xunique{$tested}} ];
+ my @unique_to_this_index = ();
+ for my $s (@seenthis) {
+ push @unique_to_this_index, $s
+ unless $seen_in_all_others{$s};
+ }
+ return \@unique_to_this_index;
}
sub get_complement {
@@ -214,17 +209,14 @@ sub _complement_engine {
my $tested = pop(@_);
my $seenrefsref = _calc_seen1(@_);
my ($unionref, $seenref) = _calculate_union_seen_only($seenrefsref);
- my %seen = %{$seenref};
- my @union = keys %{$unionref};
# Calculate %xcomplement
- # Inputs: $seenrefsref @union %seen
+ # Inputs: $seenrefsref @union (keys %$unionref)
my (%xcomplement);
for (my $i = 0; $i <= $#{$seenrefsref}; $i++) {
- my %seenthis = %{$seen{$i}};
my @complementthis = ();
- foreach (@union) {
- push(@complementthis, $_) unless (exists $seenthis{$_});
+ foreach my $k (keys %{$unionref}) {
+ push(@complementthis, $k) unless (exists $seenref->{$i}->{$k});
}
$xcomplement{$i} = \@complementthis;
}
@@ -237,21 +229,22 @@ sub get_symmetric_difference {
sub get_symmetric_difference_ref {
my ($argref, $unsorted) = _alt_construct_tester(@_);
- $unsorted
+ $unsorted
? return _symmetric_difference_engine(_argument_checker($argref))
: return [ sort @{_symmetric_difference_engine(_argument_checker($argref))} ];
}
sub _symmetric_difference_engine {
+ # Get those items which do not appear in more than one of several lists (their symmetric_difference);
my $seenrefsref = _calc_seen1(@_);
- my ($unionref, $xintersectionref) =
- _calculate_union_xintersection_only($seenrefsref);
- my @union = keys %{$unionref};
- my $sharedref = _calculate_hash_shared($xintersectionref);
+ my $unionref = _calculate_union_only($seenrefsref);
+
+ my $sharedref = _calculate_sharedref($seenrefsref);
+
my (@symmetric_difference);
- foreach (@union) {
- push(@symmetric_difference, $_) unless exists ${$sharedref}{$_};
+ for my $k (keys %{$unionref}) {
+ push(@symmetric_difference, $k) unless exists $sharedref->{$k};
}
return \@symmetric_difference;
}
@@ -265,19 +258,16 @@ sub get_shared {
sub get_shared_ref {
my ($argref, $unsorted) = _alt_construct_tester(@_);
- $unsorted
+ $unsorted
? return _shared_engine(_argument_checker($argref))
: return [ sort @{_shared_engine(_argument_checker($argref))} ];
}
sub _shared_engine {
my $seenrefsref = _calc_seen1(@_);
- # Calculate @shared
- # Inputs: %xintersection
- my $xintersectionref = _calculate_xintersection_only($seenrefsref);
- my $sharedref = _calculate_hash_shared($xintersectionref);
- my @shared = keys %{$sharedref};
- return \@shared;
+
+ my $sharedref = _calculate_sharedref($seenrefsref);
+ return [ keys %{$sharedref} ];
}
sub get_nonintersection {
@@ -286,22 +276,28 @@ sub get_nonintersection {
sub get_nonintersection_ref {
my ($argref, $unsorted) = _alt_construct_tester(@_);
- $unsorted
+ $unsorted
? return _nonintersection_engine(_argument_checker($argref))
: return [ sort @{_nonintersection_engine(_argument_checker($argref))} ];
}
sub _nonintersection_engine {
my $seenrefsref = _calc_seen1(@_);
- my ($unionref, $xintersectionref) =
- _calculate_union_xintersection_only($seenrefsref);
- my @union = keys %{$unionref};
- my $intersectionref = _calculate_hash_intersection($xintersectionref);
+ my $unionref =
+ _calculate_union_only($seenrefsref);
+ my @vals = sort { scalar(keys(%{$a})) <=> scalar(keys(%{$b})) }
+ @{$seenrefsref};
+ my %intersection = map { $_ => 1 } keys %{$vals[0]};
+ for my $l ( 1..$#vals ) {
+ %intersection = map { $_ => 1 }
+ grep { exists $intersection{$_} }
+ keys %{$vals[$l]};
+ }
# Calculate nonintersection
- # Inputs: @union %intersection
+ # Inputs: @union (keys %$unionref) %intersection
my (@nonintersection);
- foreach (@union) {
- push(@nonintersection, $_) unless exists ${$intersectionref}{$_};
+ for my $k (keys %{$unionref}) {
+ push(@nonintersection, $k) unless exists $intersection{$k};
}
return \@nonintersection;
}
@@ -356,18 +352,14 @@ sub is_LdisjointR {
sub _is_LdisjointR_engine {
my $testedref = pop(@_);
my $seenrefsref = _calc_seen1(@_);
- my $xintersectionref = _calculate_xintersection_only($seenrefsref);
- my (@xdisjoint);
- for (my $i = 0; $i <= @{$seenrefsref}; $i++) {
- foreach (keys %{$xintersectionref}) {
- my ($left, $right) = split /_/, $_;
- $xdisjoint[$left][$right] = $xdisjoint[$right][$left] =
- ! scalar(keys %{${$xintersectionref}{$_}}) ? 1 : 0;
+ my $disjoint = 1; # start out assuming disjoint status
+ OUTER: for my $k (keys %{$seenrefsref->[$testedref->[0]]}) {
+ if ($seenrefsref->[$testedref->[1]]->{$k}) {
+ $disjoint = 0;
+ last OUTER;
}
- $xdisjoint[$i][$i] = 0;
}
- my $disjoint_status = $xdisjoint[${$testedref}[1]][${$testedref}[0]];
- return $disjoint_status;
+ return $disjoint;
}
sub print_subset_chart {
@@ -392,16 +384,16 @@ sub _print_equivalence_chart_engine {
my $xequivalentref = _equivalent_subengine($seenrefsref);
my $title = 'Equivalence';
_chart_engine_multiple($xequivalentref, $title);
-}
+}
sub is_member_which {
return @{ is_member_which_ref(@_) };
-}
+}
sub is_member_which_ref {
my $argref = _alt_construct_tester_1(@_);
return _is_member_which_engine(_argument_checker_1($argref));
-}
+}
sub _is_member_which_engine {
my $arg = pop(@_);
@@ -417,7 +409,7 @@ sub _is_member_which_engine {
sub is_member_any {
my $argref = _alt_construct_tester_1(@_);
return _is_member_any_engine(_argument_checker_1($argref));
-}
+}
sub _is_member_any_engine {
my $tested = pop(@_);
@@ -456,7 +448,7 @@ sub _are_members_which_engine {
sub are_members_any {
my $argref = _alt_construct_tester_2(@_);
return _are_members_any_engine(_argument_checker_2($argref));
-}
+}
sub _are_members_any_engine {
my $testedref = pop(@_);
@@ -481,7 +473,7 @@ sub get_bag {
sub get_bag_ref {
my ($argref, $unsorted) = _alt_construct_tester(@_);
- $unsorted
+ $unsorted
? return _bag_engine(_argument_checker($argref))
: return [ sort @{_bag_engine(_argument_checker($argref))} ];
}
@@ -489,7 +481,7 @@ sub get_bag_ref {
sub _bag_engine {
my @listrefs = @_;
my (@bag);
- if (ref($listrefs[0]) eq 'ARRAY') {
+ if (ref($listrefs[0]) eq 'ARRAY') {
foreach my $lref (@listrefs) {
foreach my $el (@{$lref}) {
push(@bag, $el);
@@ -521,20 +513,20 @@ List::Compare::Functional - Compare elements of two or more lists
=head1 VERSION
-This document refers to version 0.37 of List::Compare::Functional.
-This version was released June 07, 2008. The first released
-version of List::Compare::Functional was v0.21. Its version numbers
-are set to be consistent with the other parts of the List::Compare
+This document refers to version 0.53 of List::Compare::Functional.
+This version was released June 07 2015. The first released
+version of List::Compare::Functional was v0.21. Its version numbers
+are set to be consistent with the other parts of the List::Compare
distribution.
=head2 Notice of Interface Changes
-Certain significant changes to the interface to List::Compare::Functional
-were made with the introduction of Version 0.25 in April 2004. The
-documentation immediately below reflects those changes, so if you are
-first using this module with that or a later version, simply read and
-follow the documentation below. If, however, you used List::Compare::Functional
-prior to that version, see the discussion of interface changes farther
+Certain significant changes to the interface to List::Compare::Functional
+were made with the introduction of Version 0.25 in April 2004. The
+documentation immediately below reflects those changes, so if you are
+first using this module with that or a later version, simply read and
+follow the documentation below. If, however, you used List::Compare::Functional
+prior to that version, see the discussion of interface changes farther
below: April 2004 Change of Interface.
=head1 SYNOPSIS
@@ -545,22 +537,22 @@ List::Compare::Functional exports no subroutines by default.
use List::Compare::Functional qw(:originals :aliases);
-will import all publicly available subroutines from
-List::Compare::Functional. The model for importing just one subroutine from
+will import all publicly available subroutines from
+List::Compare::Functional. The model for importing just one subroutine from
List::Compare::Functional is:
use List::Compare::Functional qw( get_intersection );
-It will probably be most convenient for the user to import functions by
+It will probably be most convenient for the user to import functions by
using one of the two following export tags:
use List::Compare::Functional qw(:main :mainrefs);
-The assignment of the various comparison functions to export tags is
+The assignment of the various comparison functions to export tags is
discussed below.
-For clarity, we shall begin by discussing comparisons of just two lists at
-a time. Farther below, we shall discuss comparisons among three or more
+For clarity, we shall begin by discussing comparisons of just two lists at
+a time. Farther below, we shall discuss comparisons among three or more
lists at a time.
=head2 Comparing Two Lists Held in Arrays
@@ -580,16 +572,16 @@ Get those items which appear at least once in both lists (their intersection).
@intersection = get_intersection( [ \@Llist, \@Rlist ] );
-Note that you could place the references to the lists being compared into
+Note that you could place the references to the lists being compared into
a named array and then pass C<get_intersection()> a reference to that array.
@to_be_compared = ( \@Llist, \@Rlist );
@intersection = get_intersection( \@to_be_compared );
-Beginning with version 0.29 (May 2004), List::Compare::Functional now offers
-an additional way of passing arguments to its various functions. If you
-prefer to see a more explicit delineation among the types of arguments passed
-to a function, pass a single hash reference which holds the lists being
+Beginning with version 0.29 (May 2004), List::Compare::Functional now offers
+an additional way of passing arguments to its various functions. If you
+prefer to see a more explicit delineation among the types of arguments passed
+to a function, pass a single hash reference which holds the lists being
compared in an anonymous array which is the value corresponding to key C<lists>:
@intersection = get_intersection( {
@@ -638,8 +630,8 @@ or
=item *
-Make a bag of all those items in both lists. The bag differs from the
-union of the two lists in that it holds as many copies of individual
+Make a bag of all those items in both lists. The bag differs from the
+union of the two lists in that it holds as many copies of individual
elements as appear in the original lists.
@bag = get_bag( [ \@Llist, \@Rlist ] );
@@ -650,9 +642,9 @@ or
=item *
-An alternative approach to the above functions: If you do not immediately
-require an array as the return value of the function call, but simply need
-a I<reference> to an (anonymous) array, use one of the following
+An alternative approach to the above functions: If you do not immediately
+require an array as the return value of the function call, but simply need
+a I<reference> to an (anonymous) array, use one of the following
parallel functions:
$intersection_ref = get_intersection_ref( [ \@Llist, \@Rlist ] );
@@ -666,25 +658,25 @@ parallel functions:
or
- $intersection_ref =
+ $intersection_ref =
get_intersection_ref( { lists => [ \@Llist, \@Rlist ] } );
- $union_ref =
+ $union_ref =
get_union_ref( { lists => [ \@Llist, \@Rlist ] } );
- $Lonly_ref =
+ $Lonly_ref =
get_unique_ref( { lists => [ \@Llist, \@Rlist ] } );
- $Ronly_ref =
+ $Ronly_ref =
get_complement_ref( { lists => [ \@Llist, \@Rlist ] } );
- $LorRonly_ref =
+ $LorRonly_ref =
get_symmetric_difference_ref( { lists => [ \@Llist, \@Rlist ] } );
- $LorRonly_ref =
+ $LorRonly_ref =
get_symdiff_ref( { lists => [ \@Llist, \@Rlist ] } );
# alias
- $bag_ref =
+ $bag_ref =
get_bag_ref( { lists => [ \@Llist, \@Rlist ] } );
=item *
-Return a true value if the first list ('L' for 'left') is a subset of the
+Return a true value if the first list ('L' for 'left') is a subset of the
second list ('R' for 'right').
$LR = is_LsubsetR( [ \@Llist, \@Rlist ] );
@@ -705,7 +697,7 @@ or
=item *
-Return a true value if L and R are equivalent, I<i.e.,> if every element
+Return a true value if L and R are equivalent, I<i.e.,> if every element
in L appears at least once in R and I<vice versa>.
$eqv = is_LequivalentR( [ \@Llist, \@Rlist ] );
@@ -713,18 +705,18 @@ in L appears at least once in R and I<vice versa>.
or
- $eqv = is_LequivalentR( { lists => [ \@Llist, \@Rlist ] } );
+ $eqv = is_LequivalentR( { lists => [ \@Llist, \@Rlist ] } );
=item *
-Return a true value if L and R are disjoint, I<i.e.,> if L and R have
+Return a true value if L and R are disjoint, I<i.e.,> if L and R have
no common elements.
$disj = is_LdisjointR( [ \@Llist, \@Rlist ] );
or
- $disj = is_LdisjointR( { lists => [ \@Llist, \@Rlist ] } );
+ $disj = is_LdisjointR( { lists => [ \@Llist, \@Rlist ] } );
=item *
@@ -734,23 +726,23 @@ Pretty-print a chart showing whether one list is a subset of the other.
or
- print_subset_chart( { lists => [ \@Llist, \@Rlist ] } );
+ print_subset_chart( { lists => [ \@Llist, \@Rlist ] } );
=item *
-Pretty-print a chart showing whether the two lists are equivalent (same
+Pretty-print a chart showing whether the two lists are equivalent (same
elements found at least once in both).
print_equivalence_chart( [ \@Llist, \@Rlist ] );
or
- print_equivalence_chart( { lists => [ \@Llist, \@Rlist ] } );
+ print_equivalence_chart( { lists => [ \@Llist, \@Rlist ] } );
=item *
-Determine in I<which> (if any) of the lists a given string can be found.
-In list context, return a list of those indices in the argument list
+Determine in I<which> (if any) of the lists a given string can be found.
+In list context, return a list of those indices in the argument list
corresponding to lists holding the string being tested.
@memb_arr = is_member_which( [ \@Llist, \@Rlist ] , [ 'abel' ] );
@@ -766,13 +758,13 @@ In the example above, C<@memb_arr> will be:
( 0 )
-because C<'abel'> is found only in C<@Al> which holds position C<0> in the
+because C<'abel'> is found only in C<@Al> which holds position C<0> in the
list of arguments passed to C<new()>.
=item *
-As with other List::Compare::Functional functions which return a list, you
-may wish the above function returned a (scalar) reference to an array
+As with other List::Compare::Functional functions which return a list, you
+may wish the above function returned a (scalar) reference to an array
holding the list:
$memb_arr_ref = is_member_which_ref( [ \@Llist, \@Rlist ] , [ 'baker' ] );
@@ -788,23 +780,23 @@ In the example above, C<$memb_arr_ref> will be:
[ 0, 1 ]
-because C<'baker'> is found in C<@Llist> and C<@Rlist>, which hold positions
+because C<'baker'> is found in C<@Llist> and C<@Rlist>, which hold positions
C<0> and C<1>, respectively, in the list of arguments passed to C<new()>.
B<Note:> functions C<is_member_which()> and C<is_member_which_ref> test
-only one string at a time and hence take only one argument. To test more
+only one string at a time and hence take only one argument. To test more
than one string at a time see the next function, C<are_members_which()>.
=item *
-Determine in C<which> (if any) of the lists passed as arguments one or
-more given strings can be found. The lists beings searched are placed in an
-array, a reference to which is the first argument passed to
-C<are_members_which()>. The strings to be tested are also placed in an
+Determine in C<which> (if any) of the lists passed as arguments one or
+more given strings can be found. The lists beings searched are placed in an
+array, a reference to which is the first argument passed to
+C<are_members_which()>. The strings to be tested are also placed in an
array, a reference to which is the second argument passed to that function.
- $memb_hash_ref =
- are_members_which( [ \@Llist, \@Rlist ] ,
+ $memb_hash_ref =
+ are_members_which( [ \@Llist, \@Rlist ] ,
[ qw| abel baker fargo hilton zebra | ]
);
@@ -815,10 +807,10 @@ or
items => [ qw| abel baker fargo hilton zebra | ], # value is arrayref
} );
-The return value is a reference to a hash of arrays. The
-key for each element in this hash is the string being tested. Each element's
-value is a reference to an anonymous array whose elements are those indices in
-the constructor's argument list corresponding to lists holding the strings
+The return value is a reference to a hash of arrays. The
+key for each element in this hash is the string being tested. Each element's
+value is a reference to an anonymous array whose elements are those indices in
+the constructor's argument list corresponding to lists holding the strings
being tested. In the examples above, C<$memb_hash_ref> will be:
{
@@ -829,14 +821,14 @@ being tested. In the examples above, C<$memb_hash_ref> will be:
zebra => [ ],
};
-B<Note:> C<are_members_which()> can take more than one argument;
-C<is_member_which()> and C<is_member_which_ref()> each take only one argument.
+B<Note:> C<are_members_which()> can take more than one argument;
+C<is_member_which()> and C<is_member_which_ref()> each take only one argument.
Unlike those functions, C<are_members_which()> returns a hash reference.
=item *
-Determine whether a given string can be found in I<any> of the lists passed as
-arguments. Return C<1> if a specified string can be found in any of the lists
+Determine whether a given string can be found in I<any> of the lists passed as
+arguments. Return C<1> if a specified string can be found in any of the lists
and C<0> if not.
$found = is_member_any( [ \@Llist, \@Rlist ] , [ 'abel' ] );
@@ -848,19 +840,19 @@ or
item => 'abel', # value is string
} );
-In the example above, C<$found> will be C<1> because C<'abel'> is found in one
+In the example above, C<$found> will be C<1> because C<'abel'> is found in one
or more of the lists passed as arguments to C<new()>.
=item *
-Determine whether a specified string or strings can be found in I<any> of the
-lists passed as arguments. The lists beings searched are placed in an
-array, a reference to which is the first argument passed to
-C<are_members_any()>. The strings to be tested are also placed in an
+Determine whether a specified string or strings can be found in I<any> of the
+lists passed as arguments. The lists beings searched are placed in an
+array, a reference to which is the first argument passed to
+C<are_members_any()>. The strings to be tested are also placed in an
array, a reference to which is the second argument passed to that function.
- $memb_hash_ref =
- are_members_any( [ \@Llist, \@Rlist ] ,
+ $memb_hash_ref =
+ are_members_any( [ \@Llist, \@Rlist ] ,
[ qw| abel baker fargo hilton zebra | ]
);
@@ -871,9 +863,9 @@ or
items => [ qw| abel baker fargo hilton zebra | ], # value is arrayref
} );
-The return value is a reference to a hash where an element's key is the
-string being tested and the element's value is C<1> if the string can be
-found in I<any> of the lists and C<0> if not. In the examples above,
+The return value is a reference to a hash where an element's key is the
+string being tested and the element's value is C<1> if the string can be
+found in I<any> of the lists and C<0> if not. In the examples above,
C<$memb_hash_ref> will be:
{
@@ -884,7 +876,7 @@ C<$memb_hash_ref> will be:
zebra => 0,
};
-C<zebra>'s value is C<0> because C<zebra> is not found in either of the lists
+C<zebra>'s value is C<0> because C<zebra> is not found in either of the lists
passed as arguments to C<are_members_any()>.
=item *
@@ -932,14 +924,14 @@ or
=item *
-To get those items which are unique to a particular list, provide C<get_unique()>
-with two array references. The first holds references to the arrays
-which in turn hold the individual lists being compared. The second holds
-the index position in the first reference of the particular list under
-consideration. Example: To get elements unique to C<@Carmen>:
+To get those items which are unique to a particular list, provide C<get_unique()>
+with two array references. The first holds references to the arrays
+which in turn hold the individual lists being compared. The second holds
+the index position in the first reference of the particular list under
+consideration. Example: To get elements unique to C<@Carmen>:
@Lonly = get_unique(
- [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
+ [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
[ 2 ]
);
@@ -950,7 +942,7 @@ or
item => 2, # value is number
} );
-If no index position is passed to C<get_unique()> it will default to C<0>
+If no index position is passed to C<get_unique()> it will default to C<0>
and report items unique to the first list passed to the function. Hence,
@Lonly = get_unique( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -961,8 +953,8 @@ is same as:
=item *
-Should you need to identify the items unique to I<each> of the lists under
-consideration, call C<get_unique_all> and get a reference to an array of
+Should you need to identify the items unique to I<each> of the lists under
+consideration, call C<get_unique_all> and get a reference to an array of
array references:
$unique_all_ref = get_unique_all(
@@ -977,12 +969,12 @@ or
=item *
-To get those items which appear only in lists I<other than> one particular
-list, pass two array references to the C<get_complement()> function.
-The first holds references to the arrays which in turn hold the individual lists
-being compared. The second holds the index position in the first reference
-of the particular list under consideration. Example: to get all the
-elements found in lists other than C<@Don>:
+To get those items which appear only in lists I<other than> one particular
+list, pass two array references to the C<get_complement()> function.
+The first holds references to the arrays which in turn hold the individual lists
+being compared. The second holds the index position in the first reference
+of the particular list under consideration. Example: to get all the
+elements found in lists other than C<@Don>:
@Ronly = get_complement(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
@@ -996,8 +988,8 @@ or
item => 3, # value is number
} );
-If no index position is passed to C<get_complement()> it will default to C<0>
-and report items found in all lists I<other than> the first list passed to
+If no index position is passed to C<get_complement()> it will default to C<0>
+and report items found in all lists I<other than> the first list passed to
C<get_complement()>.
@Lonly = get_complement( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1008,8 +1000,8 @@ is same as:
=item *
-Should you need to identify the items not found in I<each> of the lists under
-consideration, call C<get_complement_all> and get a reference to an array of
+Should you need to identify the items not found in I<each> of the lists under
+consideration, call C<get_complement_all> and get a reference to an array of
array references:
$complement_all_ref = get_complement_all(
@@ -1024,7 +1016,7 @@ or
=item *
-Get those items which do I<not> appear in I<more than one> of several lists
+Get those items which do I<not> appear in I<more than one> of several lists
(their symmetric_difference);
@LorRonly = get_symmetric_difference( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1038,8 +1030,8 @@ or
=item *
-Get those items found in I<any> of several lists which do I<not> appear
-in C<all> of the lists (I<i.e.,> all items except those found in the
+Get those items found in I<any> of several lists which do I<not> appear
+in C<all> of the lists (I<i.e.,> all items except those found in the
intersection of the lists):
@nonintersection = get_nonintersection(
@@ -1053,7 +1045,7 @@ or
=item *
-Get those items which appear in I<more than one> of several lists
+Get those items which appear in I<more than one> of several lists
(I<i.e.,> all items except those found in their symmetric difference);
@shared = get_shared( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1066,8 +1058,8 @@ or
=item *
-Make a bag of every item found in every list. The bag differs from the
-union of the two lists in that it holds as many copies of individual
+Make a bag of every item found in every list. The bag differs from the
+union of the two lists in that it holds as many copies of individual
elements as appear in the original lists.
@bag = get_bag( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1080,19 +1072,19 @@ or
=item *
-An alternative approach to the above functions: If you do not immediately
-require an array as the return value of the function, but simply need
+An alternative approach to the above functions: If you do not immediately
+require an array as the return value of the function, but simply need
a I<reference> to an array, use one of the following parallel functions:
- $intersection_ref = get_intersection_ref(
+ $intersection_ref = get_intersection_ref(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
- $union_ref = get_union_ref(
+ $union_ref = get_union_ref(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
- $Lonly_ref = get_unique_ref(
+ $Lonly_ref = get_unique_ref(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
- $Ronly_ref = get_complement_ref(
+ $Ronly_ref = get_complement_ref(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
- $LorRonly_ref = get_symmetric_difference_ref(
+ $LorRonly_ref = get_symmetric_difference_ref(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
$LorRonly_ref = get_symdiff_ref( # alias
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1100,25 +1092,25 @@ a I<reference> to an array, use one of the following parallel functions:
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
$shared_ref = get_shared_ref(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
- $bag_ref = get_bag_ref(
+ $bag_ref = get_bag_ref(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
=item *
-To determine whether one particular list is a subset of another of the
-lists passed to the function, pass to C<is_LsubsetR()> two array references.
-The first of these is a reference to an array of array
-references, the arrays holding the lists under consideration. The
-second is a reference to a two-element array consisting of the
-index of the presumed subset, followed by the index position of the presumed
-superset. A true value (C<1>) is returned if the first (left-hand) element
-in the second reference list is a subset of the second (right-hand) element;
+To determine whether one particular list is a subset of another of the
+lists passed to the function, pass to C<is_LsubsetR()> two array references.
+The first of these is a reference to an array of array
+references, the arrays holding the lists under consideration. The
+second is a reference to a two-element array consisting of the
+index of the presumed subset, followed by the index position of the presumed
+superset. A true value (C<1>) is returned if the first (left-hand) element
+in the second reference list is a subset of the second (right-hand) element;
a false value (C<0>) is returned otherwise.
Example: To determine whether C<@Ed> is a subset of C<@Carmen>, call:
$LR = is_LsubsetR(
- [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
+ [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
[ 4, 2 ]
);
@@ -1129,8 +1121,8 @@ or
pair => [ 4, 2 ], # value is arrayref
} );
-If only the first reference (to the array of lists) is passed to
-C<is_LsubsetR>, then the function's second argument defaults to C<(0,1)> and
+If only the first reference (to the array of lists) is passed to
+C<is_LsubsetR>, then the function's second argument defaults to C<(0,1)> and
compares the first two lists passed to the constructor. So,
$LR = is_LsubsetR([ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1141,7 +1133,7 @@ compares the first two lists passed to the constructor. So,
=item *
-To reverse the order in which the particular lists are evaluated for
+To reverse the order in which the particular lists are evaluated for
superset/subset status, call C<is_RsubsetL>:
$RL = is_RsubsetL([ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], [2,4] );
@@ -1155,21 +1147,21 @@ or
=item *
-List::Compare::Functional considers two lists to be equivalent if
-every element in one list appears at least once in R and I<vice versa>.
-To determine whether one particular list passed to the function is
-equivalent to another of the lists passed to the function, provide
-C<is_LequivalentR()> with two array references.
-The first is a reference to an array of array
-references, the arrays holding the lists under consideration. The
-second of these is a reference to a two-element array consisting of the
-two lists being tested for equivalence. A true value (C<1>) is returned if
+List::Compare::Functional considers two lists to be equivalent if
+every element in one list appears at least once in R and I<vice versa>.
+To determine whether one particular list passed to the function is
+equivalent to another of the lists passed to the function, provide
+C<is_LequivalentR()> with two array references.
+The first is a reference to an array of array
+references, the arrays holding the lists under consideration. The
+second of these is a reference to a two-element array consisting of the
+two lists being tested for equivalence. A true value (C<1>) is returned if
the lists are equivalent; a false value (C<0>) is returned otherwise.
-
+
Example: To determine whether C<@Don> and C<@Ed> are equivalent, call:
$eqv = is_LequivalentR(
- [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
+ [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
[3,4]
);
@@ -1185,7 +1177,7 @@ or
pair => [3,4],
} );
-If no arguments are passed, C<is_LequivalentR> defaults to C<[0,1]> and
+If no arguments are passed, C<is_LequivalentR> defaults to C<[0,1]> and
compares the first two lists passed to the function. So,
$eqv = is_LequivalentR( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1196,19 +1188,19 @@ compares the first two lists passed to the function. So,
=item *
-To determine whether any two of the lists passed to the function are
-disjoint from one another (I<i.e.,> have no common members), provide
+To determine whether any two of the lists passed to the function are
+disjoint from one another (I<i.e.,> have no common members), provide
C<is_LdisjointR()> with two array references.
-The first is a reference to an array of array
-references, the arrays holding the lists under consideration. The
-second of these is a reference to a two-element array consisting of the
-two lists being tested for disjointedness. A true value (C<1>) is returned if
+The first is a reference to an array of array
+references, the arrays holding the lists under consideration. The
+second of these is a reference to a two-element array consisting of the
+two lists being tested for disjointedness. A true value (C<1>) is returned if
the lists are disjoint; a false value (C<0>) is returned otherwise.
Example: To determine whether C<@Don> and C<@Ed> are disjoint, call:
$disj = is_LdisjointR(
- [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
+ [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
[3,4]
);
@@ -1221,7 +1213,7 @@ or
=item *
-Pretty-print a chart showing the subset relationships among the various
+Pretty-print a chart showing the subset relationships among the various
source lists:
print_subset_chart( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1232,7 +1224,7 @@ or
=item *
-Pretty-print a chart showing the equivalence relationships among the
+Pretty-print a chart showing the equivalence relationships among the
various source lists:
print_equivalence_chart( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
@@ -1243,12 +1235,12 @@ or
=item *
-Determine in I<which> (if any) of several lists a given string can be found.
-Pass two array references, the first of which holds references to arrays
-holding the lists under consideration, and the second of which holds a
+Determine in I<which> (if any) of several lists a given string can be found.
+Pass two array references, the first of which holds references to arrays
+holding the lists under consideration, and the second of which holds a
single-item list consisting of the string being tested.
- @memb_arr = is_member_which(
+ @memb_arr = is_member_which(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
[ 'abel' ]
);
@@ -1260,18 +1252,18 @@ or
item => 'abel', # value is string
} );
-In list context, return a list of those indices in the function's
-argument list corresponding to lists holding the string being tested.
+In list context, return a list of those indices in the function's
+argument list corresponding to lists holding the string being tested.
In the example above, C<@memb_arr> will be:
( 0 )
-because C<'abel'> is found only in C<@Al> which holds position C<0> in the
+because C<'abel'> is found only in C<@Al> which holds position C<0> in the
list of arguments passed to C<is_member_which()>.
=item *
-As with other List::Compare::Functional functions which return a list, you may
+As with other List::Compare::Functional functions which return a list, you may
wish the above function returned a reference to an array holding the list:
$memb_arr_ref = is_member_which_ref(
@@ -1290,21 +1282,21 @@ In the example above, C<$memb_arr_ref> will be:
[ 3, 4 ]
-because C<'jerky'> is found in C<@Don> and C<@Ed>, which hold positions
-C<3> and C<4>, respectively, in the list of arguments passed to
+because C<'jerky'> is found in C<@Don> and C<@Ed>, which hold positions
+C<3> and C<4>, respectively, in the list of arguments passed to
C<is_member_which()>.
B<Note:> functions C<is_member_which()> and C<is_member_which_ref> test
-only one string at a time and hence take only one element in the second
-array reference argument. To test more than one string at a time see
+only one string at a time and hence take only one element in the second
+array reference argument. To test more than one string at a time see
the next function, C<are_members_which()>.
=item *
-Determine in C<which> (if any) of several lists one or more given strings
-can be found. Pass two array references, the first of which holds references
-to arrays holding the lists under consideration, and the second of which
-holds a list of the strings being tested.
+Determine in C<which> (if any) of several lists one or more given strings
+can be found. Pass two array references, the first of which holds references
+to arrays holding the lists under consideration, and the second of which
+holds a list of the strings being tested.
$memb_hash_ref = are_members_which(
[ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
@@ -1318,10 +1310,10 @@ or
items => [ qw| abel baker fargo hilton zebra | ], # value is arrayref
} );
-The return valus is a reference to a hash of arrays. In this hash,
-each element's value is a reference to an anonymous array whose
-elements are those indices in the argument list corresponding to
-lists holding the strings being tested. In the two examples above,
+The return valus is a reference to a hash of arrays. In this hash,
+each element's value is a reference to an anonymous array whose
+elements are those indices in the argument list corresponding to
+lists holding the strings being tested. In the two examples above,
C<$memb_hash_ref> will be:
{
@@ -1332,18 +1324,18 @@ C<$memb_hash_ref> will be:
zebra => [ ],
};
-B<Note:> C<are_members_which()> tests more than one string at a time. Hence,
+B<Note:> C<are_members_which()> tests more than one string at a time. Hence,
its second array reference argument can take more than one element.
-C<is_member_which()> and C<is_member_which_ref()> each take only one element
-in their second array reference arguments. C<are_members_which()> returns a
-hash reference; the other functions return either a list or a reference to an
+C<is_member_which()> and C<is_member_which_ref()> each take only one element
+in their second array reference arguments. C<are_members_which()> returns a
+hash reference; the other functions return either a list or a reference to an
array holding that list, depending on context.
=item *
-Determine whether a given string can be found in I<any> of several lists.
-Pass two array references, the first of which holds references
-to arrays holding the lists under consideration, and the second of which
+Determine whether a given string can be found in I<any> of several lists.
+Pass two array references, the first of which holds references
+to arrays holding the lists under consideration, and the second of which
holds a single-item list of the string being tested.
$found = is_member_any(
@@ -1358,16 +1350,16 @@ or
item => 'abel', # value is string
} );
-The return value is C<1> if a specified string can be found in I<any> of
-the lists and C<0> if not. In the example above, C<$found> will be
-C<1> because C<abel> is found in one or more of the lists passed as
+The return value is C<1> if a specified string can be found in I<any> of
+the lists and C<0> if not. In the example above, C<$found> will be
+C<1> because C<abel> is found in one or more of the lists passed as
arguments to C<is_member_any()>.
=item *
Determine whether a specified string or strings can be found in I<any> of
-several lists. Pass two array references, the first of which holds references
-to arrays holding the lists under consideration, and the second of which
+several lists. Pass two array references, the first of which holds references
+to arrays holding the lists under consideration, and the second of which
holds a list of the strings being tested.
$memb_hash_ref = are_members_any(
@@ -1382,9 +1374,9 @@ or
items => [ qw| abel baker fargo hilton zebra | ], # value is arrayref
} );
-The return value is a reference to a hash where an element's key is the
-string being tested and the element's value is C<1> if the string can be
-found in any of the lists and C<0> if not. In the example above,
+The return value is a reference to a hash where an element's key is the
+string being tested and the element's value is C<1> if the string can be
+found in any of the lists and C<0> if not. In the example above,
C<$memb_hash_ref> will be:
{
@@ -1395,7 +1387,7 @@ C<$memb_hash_ref> will be:
zebra => 0,
};
-C<zebra>'s value is C<0> because C<zebra> is not found in any of the lists
+C<zebra>'s value is C<0> because C<zebra> is not found in any of the lists
passed as arguments to C<are_members_any()>.
=item *
@@ -1408,26 +1400,26 @@ Return current List::Compare::Functional version number:
=head2 Comparing Lists Held in Seen-Hashes
-What is a seen-hash? A seen-hash is a typical Perl implementation of a
-look-up table: a hash where the value for a given element represents the number
-of times the element's key is observed in a list. For the purposes of
-List::Compare::Functional, what is crucial is whether an item is observed in a
-list or not; how many times the item occurs in a list is, I<with one exception,>
-irrelevant. (That exception is the C<get_bag()> function and its fraternal
-twin C<get_bag_ref()>. In this case only, the key in each element of the
-seen-hash is placed in the bag the number of times indicated by the value of
-that element.) The value of an element in a List::Compare seen-hash must be
-a positive integer, but whether that integer is 1 or 1,000,001 is immaterial for
+What is a seen-hash? A seen-hash is a typical Perl implementation of a
+look-up table: a hash where the value for a given element represents the number
+of times the element's key is observed in a list. For the purposes of
+List::Compare::Functional, what is crucial is whether an item is observed in a
+list or not; how many times the item occurs in a list is, I<with one exception,>
+irrelevant. (That exception is the C<get_bag()> function and its fraternal
+twin C<get_bag_ref()>. In this case only, the key in each element of the
+seen-hash is placed in the bag the number of times indicated by the value of
+that element.) The value of an element in a List::Compare seen-hash must be
+a positive integer, but whether that integer is 1 or 1,000,001 is immaterial for
all List::Compare::Functional functions I<except> forming a bag.
-The two lists compared above were represented by arrays; references to
+The two lists compared above were represented by arrays; references to
those arrays were passed to the various List::Compare::Functional functions.
-They could, however, have been represented by seen-hashes such as the following
+They could, however, have been represented by seen-hashes such as the following
and passed in exactly the same manner to the various functions.
%Llist = (
abel => 2,
- baker => 1,
+ baker => 1,
camera => 1,
delta => 1,
edward => 1,
@@ -1450,13 +1442,13 @@ and passed in exactly the same manner to the various functions.
and so forth.
-To compare three or more lists simultaneously, provide the appropriate
-List::Compare::Functional function with a first array reference holding a
+To compare three or more lists simultaneously, provide the appropriate
+List::Compare::Functional function with a first array reference holding a
list of three or more references to seen-hashes. Thus,
@union = get_intersection( [ \%Alpha, \%Beta, \%Gamma ] );
-The 'single hashref' format for List::Compare::Functional functions is
+The 'single hashref' format for List::Compare::Functional functions is
also available when passing seen-hashes as arguments. Examples:
@intersection = get_intersection( {
@@ -1475,15 +1467,15 @@ also available when passing seen-hashes as arguments. Examples:
$memb_hash_ref = are_members_any( {
lists => [ \%Alpha, \%Beta, \%Gamma ],
- items => [ qw| abel baker fargo hilton zebra | ],
+ items => [ qw| abel baker fargo hilton zebra | ],
} );
=head2 Faster Results with the Unsorted Option
-By default, List::Compare::Function functions return lists sorted in Perl's
-default ASCII-betical mode. Sorting entails a performance cost, and if you
-do not need a sorted list and do not wish to pay this performance cost, you
-may call the following List::Compare::Function functions with the 'unsorted'
+By default, List::Compare::Function functions return lists sorted in Perl's
+default ASCII-betical mode. Sorting entails a performance cost, and if you
+do not need a sorted list and do not wish to pay this performance cost, you
+may call the following List::Compare::Function functions with the 'unsorted'
option:
@intersection = get_intersection( '-u', [ \@Llist, \@Rlist ] );
@@ -1504,7 +1496,7 @@ or
lists => [ \@Llist, \@Rlist ],
} );
-Should you need a reference to an unsorted list as the return value, you
+Should you need a reference to an unsorted list as the return value, you
may call the unsorted option as follows:
$intersection_ref = get_intersection_ref(
@@ -1516,20 +1508,20 @@ may call the unsorted option as follows:
=head2 General Comments
-List::Compare::Functional is a non-object-oriented implementation of very
-common Perl code used to determine interesting relationships between two
-or more lists at a time. List::Compare::Functional is based on the same
-author's List::Compare module found in the same CPAN distribution.
-List::Compare::Functional is closely modeled on the ''Accelerated''
+List::Compare::Functional is a non-object-oriented implementation of very
+common Perl code used to determine interesting relationships between two
+or more lists at a time. List::Compare::Functional is based on the same
+author's List::Compare module found in the same CPAN distribution.
+List::Compare::Functional is closely modeled on the ''Accelerated''
mode in List::Compare.
-For a discussion of the antecedents of this module, see the discussion of the
+For a discussion of the antecedents of this module, see the discussion of the
history and development of this module in the documentation to List::Compare.
=head2 List::Compare::Functional's Export Tag Groups
-By default, List::Compare::Functional exports no functions. You may import
-individual functions into your main package but may find it more convenient to
+By default, List::Compare::Functional exports no functions. You may import
+individual functions into your main package but may find it more convenient to
import via export tag groups. Four such groups are currently defined:
use List::Compare::Functional qw(:main)
@@ -1541,7 +1533,7 @@ import via export tag groups. Four such groups are currently defined:
=item *
-Tag group C<:main> includes what, in the author's opinion, are the six
+Tag group C<:main> includes what, in the author's opinion, are the six
List::Compare::Functional subroutines mostly likely to be used:
get_intersection()
@@ -1553,8 +1545,8 @@ List::Compare::Functional subroutines mostly likely to be used:
=item *
-Tag group C<:mainrefs> includes five of the six subroutines found in
-C<:main> -- all except C<is_LsubsetR()> -- in the form in which they
+Tag group C<:mainrefs> includes five of the six subroutines found in
+C<:main> -- all except C<is_LsubsetR()> -- in the form in which they
return references to arrays rather than arrays proper:
get_intersection_ref()
@@ -1565,7 +1557,7 @@ return references to arrays rather than arrays proper:
=item *
-Tag group C<:originals> includes all List::Compare::Functional subroutines
+Tag group C<:originals> includes all List::Compare::Functional subroutines
in their 'original' form, I<i.e.>, no aliases for those subroutines:
get_intersection
@@ -1600,8 +1592,8 @@ in their 'original' form, I<i.e.>, no aliases for those subroutines:
=item *
-Tag group C<:aliases> contains all List::Compare::Functional subroutines
-which are aliases for subroutines found in tag group C<:originals>. These
+Tag group C<:aliases> contains all List::Compare::Functional subroutines
+which are aliases for subroutines found in tag group C<:originals>. These
are provided simply for less typing.
get_symdiff
@@ -1612,19 +1604,19 @@ are provided simply for less typing.
=head2 April 2004 Change of Interface
-B<Note:> You can skip this section unless you used List::Compare::Functional
+B<Note:> You can skip this section unless you used List::Compare::Functional
prior to the release of Version 0.25 in April 2004.
-Version 0.25 initiated a significant change in the interface to
-this module's various functions. In order to be able to accommodate
-comparisons among more than two lists, it was necessary to change the type
-of arguments passed to the various functions. Whereas previously a
+Version 0.25 initiated a significant change in the interface to
+this module's various functions. In order to be able to accommodate
+comparisons among more than two lists, it was necessary to change the type
+of arguments passed to the various functions. Whereas previously a
typical List::Compare::Functional function would be called like this:
@intersection = get_intersection( \@Llist, \@Rlist ); # SUPERSEDED
-... now the references to the lists being compared must now be placed
-within a wrapper array (anonymous or named), a reference to which is
+... now the references to the lists being compared must now be placed
+within a wrapper array (anonymous or named), a reference to which is
now passed to the function, like so:
@intersection = get_intersection( [ \@Llist, \@Rlist ] );
@@ -1634,26 +1626,26 @@ now passed to the function, like so:
@to_be_compared = (\@Llist, \@Rlist);
@intersection = get_intersection( \@to_be_compared );
-In a similar manner, List::Compare::Functional functions could previously
-take arguments in the form of references to 'seen-hashes' instead of
+In a similar manner, List::Compare::Functional functions could previously
+take arguments in the form of references to 'seen-hashes' instead of
references to arrays:
@intersection = get_intersection( \%h0, \%h1 );
-(See above for discussion of seen-hashes.) Now, those references to
-seen-hashes must be placed within a wrapper array (anonymous or named),
+(See above for discussion of seen-hashes.) Now, those references to
+seen-hashes must be placed within a wrapper array (anonymous or named),
a reference to which is passed to the function, like so:
@intersection = get_intersection( [ \%h0, \%h1 ] );
-Also, in a similar manner, some List::Compare::Functional functions
-previously took arguments in addition to the lists being compared.
+Also, in a similar manner, some List::Compare::Functional functions
+previously took arguments in addition to the lists being compared.
These arguments were simply passed as scalars, like this:
@memb_arr = is_member_which(\@Llist, \@Rlist, 'abel');
-Now these arguments must also be placed within a wrapper array
-(anonymous or named), a reference to which is now passed to the function,
+Now these arguments must also be placed within a wrapper array
+(anonymous or named), a reference to which is now passed to the function,
like so:
@memb_arr = is_member_which( [ \@Llist, \@Rlist ], [ 'abel' ] );
@@ -1664,9 +1656,9 @@ like so:
@opts = ( 'abel' );
@memb_arr = is_member_which( \@to_be_compared, \@opts );
-As in previous versions, for a speed boost the user may provide the
-C<'-u'> or C<'--unsorted'> option as the I<first> argument to some
-List::Compare::Functional functions. Using this option, the
+As in previous versions, for a speed boost the user may provide the
+C<'-u'> or C<'--unsorted'> option as the I<first> argument to some
+List::Compare::Functional functions. Using this option, the
C<get_intersection()> function above would appear as:
@intersection = get_intersection( '-u', [ \@Llist, \@Rlist ] );
@@ -1675,21 +1667,21 @@ C<get_intersection()> function above would appear as:
@intersection = get_intersection( '--unsorted', [ \@Llist, \@Rlist ] );
-The arguments to I<any> List::Compare::Functional function will therefore
-consist possibly of the unsorted option, and then of either one or two
-references to arrays, the first of which is a reference to an array of
+The arguments to I<any> List::Compare::Functional function will therefore
+consist possibly of the unsorted option, and then of either one or two
+references to arrays, the first of which is a reference to an array of
arrays or an array of seen-hashes.
=head1 AUTHOR
-James E. Keenan (jkeenan@cpan.org). When sending correspondence, please
-include 'List::Compare::Functional' or 'List-Compare-Functional' in your
+James E. Keenan (jkeenan@cpan.org). When sending correspondence, please
+include 'List::Compare::Functional' or 'List-Compare-Functional' in your
subject line.
-Creation date: May 20, 2002. Last modification date: June 07, 2008.
-Copyright (c) 2002-08 James E. Keenan. United States. All rights reserved.
+Creation date: May 20, 2002. Last modification date: June 07 2015.
+Copyright (c) 2002-15 James E. Keenan. United States. All rights reserved.
This is free software and may be distributed under the same terms as Perl
itself.
-=cut
+=cut
@@ -1,6 +1,5 @@
package List::Compare;
-#$Id: Compare.pm 1329 2008-06-07 23:49:51Z jimk $
-$VERSION = '0.37';
+$VERSION = '0.53';
use strict;
local $^W = 1;
use Carp;
@@ -11,7 +10,7 @@ use List::Compare::Base::_Auxiliary qw(
sub new {
my $class = shift;
- my (@args, $unsorted, $accelerated, $self, $dataref, $unsortflag);
+ my (@args, $unsorted, $accelerated);
my ($argument_error_status, $nextarg, @testargs);
if (@_ == 1 and (ref($_[0]) eq 'HASH')) {
my $argref = shift;
@@ -27,7 +26,7 @@ sub new {
@args = @_;
$unsorted = ($args[0] eq '-u' or $args[0] eq '--unsorted')
? shift(@args) : '';
- $accelerated = shift(@args)
+ $accelerated = shift(@args)
if ($args[0] eq '-a' or $args[0] eq '--accelerated');
}
$argument_error_status = 1;
@@ -45,21 +44,16 @@ sub new {
croak "Must pass all array references or all hash references: $!"
unless $argument_error_status;
- # bless a ref to an empty hash into the invoking class
+ # Compose the name of the class
if (@args > 2) {
if ($accelerated) {
$class .= '::Multiple::Accelerated';
- $self = bless {}, $class;
} else {
$class .= '::Multiple';
- $self = bless {}, $class;
}
} elsif (@args == 2) {
if ($accelerated) {
$class .= '::Accelerated';
- $self = bless {}, $class;
- } else {
- $self = bless {}, $class;
}
} else {
croak "Must pass at least 2 references to \&new: $!";
@@ -67,8 +61,8 @@ sub new {
# do necessary calculations and store results in a hash
# take a reference to that hash
- $unsortflag = $unsorted ? 1 : 0;
- $dataref = $self->_init($unsortflag, @args);
+ my $self = bless {}, $class;
+ my $dataref = $self->_init(($unsorted ? 1 : 0), @args);
# initialize the object from the prepared values (Damian, p. 98)
%$self = %$dataref;
@@ -94,11 +88,11 @@ sub _init {
%seenL = %{$seenLref};
%seenR = %{$seenRref};
} else {
- foreach (@$refL) { $seenL{$_}++ }
+ foreach (@$refL) { $seenL{$_}++ }
foreach (@$refR) { $seenR{$_}++ }
@left = @$refL;
@right = @$refR;
- }
+ }
my @bag = $unsortflag ? (@left, @right) : sort(@left, @right);
my (%intersection, %union, %Lonly, %Ronly, %LorRonly);
my $LsubsetR_status = my $RsubsetL_status = 1;
@@ -131,17 +125,17 @@ sub _init {
}
}
- $data{'seenL'} = \%seenL;
- $data{'seenR'} = \%seenR;
- $data{'intersection'} = $unsortflag ? [ keys %intersection ]
+ $data{'seenL'} = \%seenL;
+ $data{'seenR'} = \%seenR;
+ $data{'intersection'} = $unsortflag ? [ keys %intersection ]
: [ sort keys %intersection ];
$data{'union'} = $unsortflag ? [ keys %union ]
: [ sort keys %union ];
- $data{'unique'} = $unsortflag ? [ keys %Lonly ]
+ $data{'unique'} = $unsortflag ? [ keys %Lonly ]
: [ sort keys %Lonly ];
- $data{'complement'} = $unsortflag ? [ keys %Ronly ]
+ $data{'complement'} = $unsortflag ? [ keys %Ronly ]
: [ sort keys %Ronly ];
- $data{'symmetric_difference'} = $unsortflag ? [ keys %LorRonly ]
+ $data{'symmetric_difference'} = $unsortflag ? [ keys %LorRonly ]
: [ sort keys %LorRonly ];
$data{'LsubsetR_status'} = $LsubsetR_status;
$data{'RsubsetL_status'} = $RsubsetL_status;
@@ -299,7 +293,7 @@ sub print_subset_chart {
sub print_equivalence_chart {
my $class = shift;
my %data = %$class;
- my @equivalent_array = ($data{'LequivalentR_status'},
+ my @equivalent_array = ($data{'LequivalentR_status'},
$data{'LequivalentR_status'});
my $title = 'Equivalence';
_chart_engine_regular(\@equivalent_array, $title);
@@ -307,7 +301,7 @@ sub print_equivalence_chart {
sub is_member_which {
return @{ is_member_which_ref(@_) };
-}
+}
sub is_member_which_ref {
my $class = shift;
@@ -322,7 +316,7 @@ sub is_member_which_ref {
(! exists ${$data{'seenR'}}{$arg}) )
{ @found = (); }
return \@found;
-}
+}
sub are_members_which {
my $class = shift;
@@ -339,7 +333,7 @@ sub are_members_which {
{ @{$found{$args[$i]}} = (); }
}
return \%found;
-}
+}
sub is_member_any {
my $class = shift;
@@ -349,7 +343,7 @@ sub is_member_any {
my $arg = shift;
( defined $data{'seenL'}{$arg} ) ||
( defined $data{'seenR'}{$arg} ) ? return 1 : return 0;
-}
+}
sub are_members_any {
my $class = shift;
@@ -363,7 +357,7 @@ sub are_members_any {
( defined $data{'seenR'}{$args[$i]} ) ? 1 : 0;
}
return \%present;
-}
+}
sub get_bag {
return @{ get_bag_ref(shift) };
@@ -389,7 +383,7 @@ use List::Compare::Base::_Auxiliary qw(
_argument_checker_0
_chart_engine_regular
_calc_seen
- _equiv_engine
+ _equiv_engine
);
sub _init {
@@ -399,7 +393,7 @@ sub _init {
($data{'L'}, $data{'R'}) = _argument_checker_0($refL, $refR);
$data{'unsort'} = $unsortflag ? 1 : 0;
return \%data;
-}
+}
sub get_intersection {
return @{ get_intersection_ref(shift) };
@@ -408,8 +402,8 @@ sub get_intersection {
sub get_intersection_ref {
my $class = shift;
my %data = %$class;
- $data{'unsort'}
- ? return _intersection_engine($data{'L'}, $data{'R'})
+ $data{'unsort'}
+ ? return _intersection_engine($data{'L'}, $data{'R'})
: return [ sort @{_intersection_engine($data{'L'}, $data{'R'})} ];
}
@@ -420,8 +414,8 @@ sub get_union {
sub get_union_ref {
my $class = shift;
my %data = %$class;
- $data{'unsort'}
- ? return _union_engine($data{'L'}, $data{'R'})
+ $data{'unsort'}
+ ? return _union_engine($data{'L'}, $data{'R'})
: return [ sort @{_union_engine($data{'L'}, $data{'R'})} ];
}
@@ -444,8 +438,8 @@ sub get_unique {
sub get_unique_ref {
my $class = shift;
my %data = %$class;
- $data{'unsort'}
- ? return _unique_engine($data{'L'}, $data{'R'})
+ $data{'unsort'}
+ ? return _unique_engine($data{'L'}, $data{'R'})
: return [ sort @{_unique_engine($data{'L'}, $data{'R'})} ];
}
@@ -466,8 +460,8 @@ sub get_complement {
sub get_complement_ref {
my $class = shift;
my %data = %$class;
- $data{'unsort'}
- ? return _complement_engine($data{'L'}, $data{'R'})
+ $data{'unsort'}
+ ? return _complement_engine($data{'L'}, $data{'R'})
: return [ sort @{_complement_engine($data{'L'}, $data{'R'})} ];
}
@@ -488,8 +482,8 @@ sub get_symmetric_difference {
sub get_symmetric_difference_ref {
my $class = shift;
my %data = %$class;
- $data{'unsort'}
- ? return _symmetric_difference_engine($data{'L'}, $data{'R'})
+ $data{'unsort'}
+ ? return _symmetric_difference_engine($data{'L'}, $data{'R'})
: return [ sort @{_symmetric_difference_engine($data{'L'}, $data{'R'})} ];
}
@@ -556,7 +550,7 @@ sub print_equivalence_chart {
sub is_member_which {
return @{ is_member_which_ref(@_) };
-}
+}
sub is_member_which_ref {
my $class = shift;
@@ -564,7 +558,7 @@ sub is_member_which_ref {
unless (@_ == 1 and ref($_[0]) ne 'ARRAY');
my %data = %$class;
return _is_member_which_engine($data{'L'}, $data{'R'}, shift);
-}
+}
sub are_members_which {
my $class = shift;
@@ -582,7 +576,7 @@ sub is_member_any {
unless (@_ == 1 and ref($_[0]) ne 'ARRAY');
my %data = %$class;
return _is_member_any_engine($data{'L'}, $data{'R'}, shift);
-}
+}
sub are_members_any {
my $class = shift;
@@ -592,7 +586,7 @@ sub are_members_any {
my (@args);
@args = @{$_[0]};
return _are_members_any_engine($data{'L'}, $data{'R'}, \@args);
-}
+}
sub get_bag {
return @{ get_bag_ref(shift) };
@@ -746,7 +740,7 @@ sub _print_equivalence_chart_engine {
my @equivalent_array = ($LequivalentR_status, $LequivalentR_status);
my $title = 'Equivalence';
_chart_engine_regular(\@equivalent_array, $title);
-}
+}
sub _is_member_which_engine {
my ($l, $r, $arg) = @_;
@@ -758,7 +752,7 @@ sub _is_member_which_engine {
(! exists ${$hrefR}{$arg}) )
{ @found = (); }
return \@found;
-}
+}
sub _are_members_which_engine {
my ($l, $r, $arg) = @_;
@@ -843,31 +837,31 @@ sub _init {
# will hold all items found in at least 2 lists
my @symmetric_difference = ();
# will hold each item found in only one list regardless of list;
- # equivalent to @union minus all items found in the lists
+ # equivalent to @union minus all items found in the lists
# underlying %xintersection
my (%intersection, %union);
# will be used to generate @intersection & @union
my %seen = ();
- # will be hash of hashes, holding seen-hashes corresponding to
+ # will be hash of hashes, holding seen-hashes corresponding to
# the source lists
my %xintersection = ();
- # will be hash of hashes, holding seen-hashes corresponding to
- # the lists containing the intersections of each permutation of
+ # will be hash of hashes, holding seen-hashes corresponding to
+ # the lists containing the intersections of each permutation of
# the source lists
my %shared = ();
# will be used to generate @shared
my @xunique = ();
- # will be array of arrays, holding the items that are unique to
+ # will be array of arrays, holding the items that are unique to
# the list whose index number is passed as an argument
my @xcomplement = ();
- # will be array of arrays, holding the items that are found in
- # any list other than the list whose index number is passed
+ # will be array of arrays, holding the items that are found in
+ # any list other than the list whose index number is passed
# as an argument
my @xdisjoint = ();
- # will be an array of arrays, holding an indicator as to whether
+ # will be an array of arrays, holding an indicator as to whether
# any pair of lists are disjoint, i.e., have no intersection
- # Calculate overall union and take steps needed to calculate overall
+ # Calculate overall union and take steps needed to calculate overall
# intersection, unique, difference, etc.
for (my $i = 0; $i <= $#arrayrefs; $i++) {
my %seenthis = ();
@@ -888,7 +882,7 @@ sub _init {
}
@union = $unsortflag ? keys %union : sort(keys %union);
- # At this point we now have %seen, @union and %xintersection available
+ # At this point we now have %seen, @union and %xintersection available
# for use in other calculations.
# Calculate overall intersection
@@ -916,14 +910,14 @@ sub _init {
for (my $i = 0; $i <= $#arrayrefs; $i++) {
my %seenthis = %{$seen{$i}};
my (@uniquethis, %deductions, %alldeductions);
- # Get those elements of %xintersection which we'll need
+ # Get those elements of %xintersection which we'll need
# to subtract from %seenthis
foreach (keys %xintersection) {
my ($left, $right) = split /_/, $_;
if ($left == $i || $right == $i) {
$deductions{$_} = $xintersection{$_};
}
- $xdisjoint[$left][$right] = $xdisjoint[$right][$left] =
+ $xdisjoint[$left][$right] = $xdisjoint[$right][$left] =
! (keys %{$xintersection{$_}}) ? 1 : 0;
}
foreach my $ded (keys %deductions) {
@@ -935,9 +929,9 @@ sub _init {
push(@uniquethis, $_) unless ($alldeductions{$_});
}
$xunique[$i] = \@uniquethis;
- $xdisjoint[$i][$i] = 0;
+ $xdisjoint[$i][$i] = 0;
}
- # @xunique is now available for use in further calculations,
+ # @xunique is now available for use in further calculations,
# such as returning the items unique to a particular source list.
# Calculate @xcomplement
@@ -950,8 +944,8 @@ sub _init {
}
$xcomplement[$i] = \@complementthis;
}
- # @xcomplement is now available for use in further calculations,
- # such as returning the items in all lists different from those in a
+ # @xcomplement is now available for use in further calculations,
+ # such as returning the items in all lists different from those in a
# particular source list.
# Calculate @shared and @symmetric_difference
@@ -1002,7 +996,7 @@ sub _init {
$data{'xdisjoint'} = \@xdisjoint;
$data{'bag'} = \@bag;
return \%data;
-}
+}
sub get_intersection {
return @{ get_intersection_ref(shift) };
@@ -1061,7 +1055,7 @@ sub get_Lonly {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_unique()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
get_unique($class, $index);
-}
+}
sub get_Lonly_ref {
my ($class, $index) = @_;
@@ -1069,7 +1063,7 @@ sub get_Lonly_ref {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_unique_ref()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
get_unique_ref($class, $index);
-}
+}
*get_Aonly = \&get_Lonly;
*get_Aonly_ref = \&get_Lonly_ref;
@@ -1101,7 +1095,7 @@ sub get_Ronly {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_complement()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
&get_complement($class, $index);
-}
+}
sub get_Ronly_ref {
my ($class, $index) = @_;
@@ -1109,7 +1103,7 @@ sub get_Ronly_ref {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_complement_ref()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
&get_complement_ref($class, $index);
-}
+}
*get_Bonly = \&get_Ronly;
*get_Bonly_ref = \&get_Ronly_ref;
@@ -1133,7 +1127,7 @@ sub get_LorRonly {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_symmetric_difference()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
get_symmetric_difference($class);
-}
+}
sub get_LorRonly_ref {
my $class = shift;
@@ -1141,7 +1135,7 @@ sub get_LorRonly_ref {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_symmetric_difference_ref()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
get_symmetric_difference_ref($class);
-}
+}
*get_AorBonly = \&get_LorRonly;
*get_AorBonly_ref = \&get_LorRonly_ref;
@@ -1204,7 +1198,7 @@ sub is_LdisjointR {
sub is_member_which {
return @{ is_member_which_ref(@_) };
-}
+}
sub is_member_which_ref {
my $class = shift;
@@ -1218,7 +1212,7 @@ sub is_member_which_ref {
push @found, $_ if (exists $seen{$_}{$arg});
}
return \@found;
-}
+}
sub are_members_which {
my $class = shift;
@@ -1238,7 +1232,7 @@ sub are_members_which {
$found{$args[$i]} = [] if (@not_found == keys %seen);
}
return \%found;
-}
+}
sub is_member_any {
my $class = shift;
@@ -1252,7 +1246,7 @@ sub is_member_any {
return 1 if (defined $seen{$k}{$arg});
}
return 0;
-}
+}
sub are_members_any {
my $class = shift;
@@ -1271,7 +1265,7 @@ sub are_members_any {
$present{$args[$i]} = 0 if (! defined $present{$args[$i]});
}
return \%present;
-}
+}
sub print_subset_chart {
my $class = shift;
@@ -1317,8 +1311,7 @@ use List::Compare::Base::_Auxiliary qw(
_equivalent_subengine
_index_message3
_index_message4
- _prepare_listrefs
- _subset_engine_multaccel
+ _subset_engine_multaccel
);
use List::Compare::Base::_Auxiliary qw(:calculate);
use List::Compare::Base::_Engine qw(
@@ -1332,11 +1325,11 @@ sub _init {
my @listrefs = _argument_checker_0(@_);
my %data = ();
for (my $i=0; $i<=$#listrefs; $i++) {
- $data{$i} = $listrefs[$i];
+ $data{$i} = $listrefs[$i];
}
$data{'unsort'} = $unsortflag ? 1 : 0;
return \%data;
-}
+}
sub get_union {
return @{ get_union_ref(shift) };
@@ -1362,13 +1355,9 @@ sub get_intersection_ref {
my %data = %$class;
my $unsortflag = $data{'unsort'};
my $aref = _prepare_listrefs(\%data);
-
- # Calculate overall intersection
- # Inputs: %xintersection
- my $xintersectionref = _calculate_xintersection_only($aref);
- my $intersectionref = _calculate_hash_intersection($xintersectionref);
- my @intersection =
- $unsortflag ? keys %{$intersectionref} : sort(keys %{$intersectionref});
+ my $intermediate_ref = _calculate_intermediate($aref);
+ my @intersection =
+ $unsortflag ? keys %{$intermediate_ref} : sort(keys %{$intermediate_ref});
return \@intersection;
}
@@ -1382,18 +1371,13 @@ sub get_nonintersection_ref {
my $unsortflag = $data{'unsort'};
my $aref = _prepare_listrefs(\%data);
- my ($unionref, $xintersectionref) =
- _calculate_union_xintersection_only($aref);
- my @union = $unsortflag ? keys %{$unionref} : sort(keys %{$unionref});
- my $intersectionref = _calculate_hash_intersection($xintersectionref);
-
- # Calculate nonintersection
- # Inputs: @union %intersection
+ my $unionref = _calculate_union_only($aref);
+ my $intermediate_ref = _calculate_intermediate($aref);
my (@nonintersection);
- foreach (@union) {
- push(@nonintersection, $_) unless exists ${$intersectionref}{$_};
+ foreach my $el (keys %{$unionref}) {
+ push(@nonintersection, $el) unless exists $intermediate_ref->{$el};
}
- return \@nonintersection;
+ return [ $unsortflag ? @nonintersection : sort(@nonintersection) ];
}
sub get_shared {
@@ -1405,12 +1389,9 @@ sub get_shared_ref {
my %data = %$class;
my $unsortflag = $data{'unsort'};
my $aref = _prepare_listrefs(\%data);
-
- # Calculate @shared
- # Inputs: %xintersection
- my $xintersectionref = _calculate_xintersection_only($aref);
- my $sharedref = _calculate_hash_shared($xintersectionref);
- my @shared = $unsortflag ? keys %{$sharedref} : sort(keys %{$sharedref});
+ my $aseenref = _calculate_array_seen_only($aref);
+ my $intermediate = _calculate_sharedref($aseenref);
+ my @shared = $unsortflag ? keys %{$intermediate} : sort(keys %{$intermediate});
return \@shared;
}
@@ -1423,17 +1404,16 @@ sub get_symmetric_difference_ref {
my %data = %$class;
my $unsortflag = $data{'unsort'};
my $aref = _prepare_listrefs(\%data);
+ my $unionref = _calculate_union_only($aref);
- my ($unionref, $xintersectionref) =
- _calculate_union_xintersection_only($aref);
- my @union = $unsortflag ? keys %{$unionref} : sort(keys %{$unionref});
+ my $aseenref = _calculate_array_seen_only($aref);
+ my $sharedref = _calculate_sharedref($aseenref);
- my $sharedref = _calculate_hash_shared($xintersectionref);
my (@symmetric_difference);
- foreach (@union) {
- push(@symmetric_difference, $_) unless exists ${$sharedref}{$_};
+ foreach my $el (keys %{$unionref}) {
+ push(@symmetric_difference, $el) unless exists $sharedref->{$el};
}
- return \@symmetric_difference;
+ return [ $unsortflag ? @symmetric_difference : sort(@symmetric_difference) ];
}
*get_symdiff = \&get_symmetric_difference;
@@ -1445,7 +1425,7 @@ sub get_LorRonly {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_symmetric_difference()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
get_symmetric_difference($class);
-}
+}
sub get_LorRonly_ref {
my $class = shift;
@@ -1453,7 +1433,7 @@ sub get_LorRonly_ref {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_symmetric_difference_ref()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
get_symmetric_difference_ref($class);
-}
+}
*get_AorBonly = \&get_LorRonly;
*get_AorBonly_ref = \&get_LorRonly_ref;
@@ -1489,7 +1469,7 @@ sub get_Lonly {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_unique()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
get_unique($class, $index);
-}
+}
sub get_Lonly_ref {
my ($class, $index) = @_;
@@ -1497,7 +1477,7 @@ sub get_Lonly_ref {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_unique_ref()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
get_unique_ref($class, $index);
-}
+}
*get_Aonly = \&get_Lonly;
*get_Aonly_ref = \&get_Lonly_ref;
@@ -1534,7 +1514,7 @@ sub get_Ronly {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_complement()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
&get_complement($class, $index);
-}
+}
sub get_Ronly_ref {
my ($class, $index) = @_;
@@ -1542,7 +1522,7 @@ sub get_Ronly_ref {
$method =~ s/.*::(\w*)$/$1/;
carp "When comparing 3 or more lists, \&$method or its alias defaults to \n ", 'get_complement_ref()', ". Though the results returned are valid, \n please consider re-coding with that method: $!";
&get_complement_ref($class, $index);
-}
+}
*get_Bonly = \&get_Ronly;
*get_Bonly_ref = \&get_Ronly_ref;
@@ -1588,24 +1568,22 @@ sub is_LdisjointR {
my %data = %$class;
my $aref = _prepare_listrefs(\%data);
my ($index_left, $index_right) = _index_message4($#{$aref}, @_);
-
- my (@xdisjoint);
- my $xintersectionref = _calculate_xintersection_only($aref);
- for (my $i = 0; $i <= $#{$aref}; $i++) {
- foreach (keys %{$xintersectionref}) {
- my ($left, $right) = split /_/, $_;
- $xdisjoint[$left][$right] = $xdisjoint[$right][$left] =
- ! scalar(keys %{${$xintersectionref}{$_}}) ? 1 : 0;
+ my $aseenref = _calculate_array_seen_only(
+ [ $aref->[$index_left], $aref->[$index_right] ]
+ );
+ my $disjoint_status = 1;
+ OUTER: for my $k (keys %{$aseenref->[0]}) {
+ if ($aseenref->[1]->{$k}) {
+ $disjoint_status = 0;
+ last OUTER;
}
- $xdisjoint[$i][$i] = 0;
}
- my $disjoint_status = $xdisjoint[$index_left][$index_right];
return $disjoint_status;
}
sub is_member_which {
return @{ is_member_which_ref(@_) };
-}
+}
sub is_member_which_ref {
my $class = shift;
@@ -1620,11 +1598,10 @@ sub is_member_which_ref {
push @found, $_ if (exists ${$seenref}{$_}{$arg});
}
return \@found;
-}
+}
sub are_members_which {
my $class = shift;
-# croak "Method call needs at least one argument: $!" unless (@_);
croak "Method call requires exactly 1 argument which must be an array reference\n holding the items to be tested: $!"
unless (@_ == 1 and ref($_[0]) eq 'ARRAY');
my %data = %{$class};
@@ -1632,9 +1609,6 @@ sub are_members_which {
my $seenref = _calculate_seen_only($aref);
my (@args, %found);
@args = @{$_[0]};
-# @args = (@_ == 1 and ref($_[0]) eq 'ARRAY')
-# ? @{$_[0]}
-# : @_;
for (my $i=0; $i<=$#args; $i++) {
my (@not_found);
foreach (sort keys %{$seenref}) {
@@ -1645,7 +1619,7 @@ sub are_members_which {
$found{$args[$i]} = [] if (@not_found == keys %{$seenref});
}
return \%found;
-}
+}
sub is_member_any {
my $class = shift;
@@ -1660,7 +1634,7 @@ sub is_member_any {
return 1 if (defined ${$seenref}{$k}{$arg});
}
return 0;
-}
+}
sub are_members_any {
my $class = shift;
@@ -1680,7 +1654,7 @@ sub are_members_any {
$present{$args[$i]} = 0 if (! defined $present{$args[$i]});
}
return \%present;
-}
+}
sub print_subset_chart {
my $class = shift;
@@ -1711,7 +1685,7 @@ sub get_bag_ref {
my $aref = _prepare_listrefs(\%data);
my (@bag);
my @listrefs = @{$aref};
- if (ref($listrefs[0]) eq 'ARRAY') {
+ if (ref($listrefs[0]) eq 'ARRAY') {
foreach my $lref (@listrefs) {
foreach my $el (@{$lref}) {
push(@bag, $el);
@@ -1745,8 +1719,8 @@ List::Compare - Compare elements of two or more lists
=head1 VERSION
-This document refers to version 0.37 of List::Compare. This version was
-released June 07, 2008.
+This document refers to version 0.53 of List::Compare. This version was
+released June 07 2015.
=head1 SYNOPSIS
@@ -1770,7 +1744,7 @@ The bare essentials:
=item * Constructor: C<new()>
-Create a List::Compare object. Put the two lists into arrays (named or
+Create a List::Compare object. Put the two lists into arrays (named or
anonymous) and pass references to the arrays to the constructor.
@Llist = qw(abel abel baker camera delta edward fargo golfer);
@@ -1778,9 +1752,9 @@ anonymous) and pass references to the arrays to the constructor.
$lc = List::Compare->new(\@Llist, \@Rlist);
-By default, List::Compare's methods return lists which are sorted using
+By default, List::Compare's methods return lists which are sorted using
Perl's default C<sort> mode: ASCII-betical sorting. Should you
-not need to have these lists sorted, you may achieve a speed boost
+not need to have these lists sorted, you may achieve a speed boost
by constructing the List::Compare object with the unsorted option:
$lc = List::Compare->new('-u', \@Llist, \@Rlist);
@@ -1791,8 +1765,8 @@ or
=item * Alternative Constructor
-If you prefer a more explicit delineation of the types of arguments passed
-to a function, you may use this 'single hashref' kind of constructor to build a
+If you prefer a more explicit delineation of the types of arguments passed
+to a function, you may use this 'single hashref' kind of constructor to build a
List::Compare object:
$lc = List::Compare->new( { lists => [\@Llist, \@Rlist] } );
@@ -1832,7 +1806,7 @@ Get those items which appear (at least once) only in the second list.
=item * C<get_symmetric_difference()>
-Get those items which appear at least once in either the first or the second
+Get those items which appear at least once in either the first or the second
list, but not both.
@LorRonly = $lc->get_symmetric_difference;
@@ -1841,17 +1815,17 @@ list, but not both.
=item * C<get_bag()>
-Make a bag of all those items in both lists. The bag differs from the
-union of the two lists in that it holds as many copies of individual
+Make a bag of all those items in both lists. The bag differs from the
+union of the two lists in that it holds as many copies of individual
elements as appear in the original lists.
@bag = $lc->get_bag;
=item * Return references rather than lists
-An alternative approach to the above methods: If you do not immediately
-require an array as the return value of the method call, but simply need
-a I<reference> to an (anonymous) array, use one of the following
+An alternative approach to the above methods: If you do not immediately
+require an array as the return value of the method call, but simply need
+a I<reference> to an (anonymous) array, use one of the following
parallel methods:
$intersection_ref = $lc->get_intersection_ref;
@@ -1867,8 +1841,8 @@ parallel methods:
=item * C<is_LsubsetR()>
-Return a true value if the first argument passed to the constructor
-('L' for 'left') is a subset of the second argument passed to the
+Return a true value if the first argument passed to the constructor
+('L' for 'left') is a subset of the second argument passed to the
constructor ('R' for 'right').
$LR = $lc->is_LsubsetR;
@@ -1879,8 +1853,8 @@ Return a true value if R is a subset of L.
=item * C<is_LequivalentR()>
-Return a true value if the two lists passed to the constructor are
-equivalent, I<i.e.> if every element in the left-hand list ('L') appears
+Return a true value if the two lists passed to the constructor are
+equivalent, I<i.e.> if every element in the left-hand list ('L') appears
at least once in the right-hand list ('R') and I<vice versa>.
$eqv = $lc->is_LequivalentR;
@@ -1888,8 +1862,8 @@ at least once in the right-hand list ('R') and I<vice versa>.
=item * C<is_LdisjointR()>
-Return a true value if the two lists passed to the constructor are
-disjoint, I<i.e.> if the two lists have zero elements in common (or, what
+Return a true value if the two lists passed to the constructor are
+disjoint, I<i.e.> if the two lists have zero elements in common (or, what
is the same thing, if their intersection is an empty set).
$disj = $lc->is_LdisjointR;
@@ -1902,16 +1876,16 @@ Pretty-print a chart showing whether one list is a subset of the other.
=item * C<print_equivalence_chart()>
-Pretty-print a chart showing whether the two lists are equivalent (same
+Pretty-print a chart showing whether the two lists are equivalent (same
elements found at least once in both).
$lc->print_equivalence_chart;
=item * C<is_member_which()>
-Determine in I<which> (if any) of the lists passed to the constructor a given
-string can be found. In list context, return a list of those indices in the
-constructor's argument list corresponding to lists holding the string being
+Determine in I<which> (if any) of the lists passed to the constructor a given
+string can be found. In list context, return a list of those indices in the
+constructor's argument list corresponding to lists holding the string being
tested.
@memb_arr = $lc->is_member_which('abel');
@@ -1920,13 +1894,13 @@ In the example above, C<@memb_arr> will be:
( 0 )
-because C<'abel'> is found only in C<@Al> which holds position C<0> in the
+because C<'abel'> is found only in C<@Al> which holds position C<0> in the
list of arguments passed to C<new()>.
-In scalar context, the return value is the number of lists passed to the
+In scalar context, the return value is the number of lists passed to the
constructor in which a given string is found.
-As with other List::Compare methods which return a list, you may wish the
+As with other List::Compare methods which return a list, you may wish the
above method returned a (scalar) reference to an array holding the list:
$memb_arr_ref = $lc->is_member_which_ref('baker');
@@ -1935,30 +1909,30 @@ In the example above, C<$memb_arr_ref> will be:
[ 0, 1 ]
-because C<'baker'> is found in C<@Llist> and C<@Rlist>, which hold positions
+because C<'baker'> is found in C<@Llist> and C<@Rlist>, which hold positions
C<0> and C<1>, respectively, in the list of arguments passed to C<new()>.
B<Note:> methods C<is_member_which()> and C<is_member_which_ref> test
-only one string at a time and hence take only one argument. To test more
+only one string at a time and hence take only one argument. To test more
than one string at a time see the next method, C<are_members_which()>.
=item * C<are_members_which()>
-Determine in I<which> (if any) of the lists passed to the constructor one or
-more given strings can be found. The strings to be tested are placed in an
+Determine in I<which> (if any) of the lists passed to the constructor one or
+more given strings can be found. The strings to be tested are placed in an
array (named or anonymous); a reference to that array is passed to the method.
- $memb_hash_ref =
+ $memb_hash_ref =
$lc->are_members_which([ qw| abel baker fargo hilton zebra | ]);
-I<Note:> In versions of List::Compare prior to 0.25 (April 2004), the
-strings to be tested could be passed as a flat list. This is no longer
+I<Note:> In versions of List::Compare prior to 0.25 (April 2004), the
+strings to be tested could be passed as a flat list. This is no longer
possible; the argument must now be a reference to an array.
-The return value is a reference to a hash of arrays. The
-key for each element in this hash is the string being tested. Each element's
-value is a reference to an anonymous array whose elements are those indices in
-the constructor's argument list corresponding to lists holding the strings
+The return value is a reference to a hash of arrays. The
+key for each element in this hash is the string being tested. Each element's
+value is a reference to an anonymous array whose elements are those indices in
+the constructor's argument list corresponding to lists holding the strings
being tested. In the examples above, C<$memb_hash_ref> will be:
{
@@ -1969,37 +1943,37 @@ being tested. In the examples above, C<$memb_hash_ref> will be:
zebra => [ ],
};
-B<Note:> C<are_members_which()> can take more than one argument;
-C<is_member_which()> and C<is_member_which_ref()> each take only one argument.
+B<Note:> C<are_members_which()> can take more than one argument;
+C<is_member_which()> and C<is_member_which_ref()> each take only one argument.
Unlike those two methods, C<are_members_which()> returns a hash reference.
=item * C<is_member_any()>
-Determine whether a given string can be found in I<any> of the lists passed as
-arguments to the constructor. Return 1 if a specified string can be found in
+Determine whether a given string can be found in I<any> of the lists passed as
+arguments to the constructor. Return 1 if a specified string can be found in
any of the lists and 0 if not.
$found = $lc->is_member_any('abel');
-In the example above, C<$found> will be C<1> because C<'abel'> is found in one
+In the example above, C<$found> will be C<1> because C<'abel'> is found in one
or more of the lists passed as arguments to C<new()>.
=item * C<are_members_any()>
-Determine whether a specified string or strings can be found in I<any> of the
-lists passed as arguments to the constructor. The strings to be tested are
-placed in an array (named or anonymous); a reference to that array is passed to
+Determine whether a specified string or strings can be found in I<any> of the
+lists passed as arguments to the constructor. The strings to be tested are
+placed in an array (named or anonymous); a reference to that array is passed to
C<are_members_any>.
$memb_hash_ref = $lc->are_members_any([ qw| abel baker fargo hilton zebra | ]);
-I<Note:> In versions of List::Compare prior to 0.25 (April 2004), the
-strings to be tested could be passed as a flat list. This is no longer
+I<Note:> In versions of List::Compare prior to 0.25 (April 2004), the
+strings to be tested could be passed as a flat list. This is no longer
possible; the argument must now be a reference to an array.
-The return value is a reference to a hash where an element's key is the
-string being tested and the element's value is 1 if the string can be
-found in I<any> of the lists and 0 if not. In the examples above,
+The return value is a reference to a hash where an element's key is the
+string being tested and the element's value is 1 if the string can be
+found in I<any> of the lists and 0 if not. In the examples above,
C<$memb_hash_ref> will be:
{
@@ -2010,7 +1984,7 @@ C<$memb_hash_ref> will be:
zebra => 0,
};
-C<zebra>'s value is C<0> because C<zebra> is not found in either of the lists
+C<zebra>'s value is C<0> because C<zebra> is not found in either of the lists
passed as arguments to C<new()>.
=item * C<get_version()>
@@ -2027,8 +2001,8 @@ Return current List::Compare version number.
=item * Constructor C<new()>
-If you are certain that you will only want the results of a I<single>
-comparison, computation may be accelerated by passing C<'-a'> or
+If you are certain that you will only want the results of a I<single>
+comparison, computation may be accelerated by passing C<'-a'> or
C<'--accelerated> as the first argument to the constructor.
@Llist = qw(abel abel baker camera delta edward fargo golfer);
@@ -2040,9 +2014,9 @@ or
$lca = List::Compare->new('--accelerated', \@Llist, \@Rlist);
-As with List::Compare's Regular case, should you not need to have
-a sorted list returned by an accelerated List::Compare method, you may
-achieve a speed boost by constructing the accelerated List::Compare object
+As with List::Compare's Regular case, should you not need to have
+a sorted list returned by an accelerated List::Compare method, you may
+achieve a speed boost by constructing the accelerated List::Compare object
with the unsorted option:
$lca = List::Compare->new('-u', '-a', \@Llist, \@Rlist);
@@ -2053,7 +2027,7 @@ or
=item * Alternative Constructor
-You may use the 'single hashref' constructor format to build a List::Compare
+You may use the 'single hashref' constructor format to build a List::Compare
object calling for the Accelerated mode:
$lca = List::Compare->new( {
@@ -2069,9 +2043,9 @@ or
unsorted => 1,
} );
-=item * Methods
+=item * Methods
-All the comparison methods available in the Regular case are available to
+All the comparison methods available in the Regular case are available to
you in the Accelerated case as well.
@intersection = $lca->get_intersection;
@@ -2101,7 +2075,7 @@ you in the Accelerated case as well.
[ qw| abel baker fargo hilton zebra | ]);
$vers = $lca->get_version;
-All the aliases for methods available in the Regular case are available to
+All the aliases for methods available in the Regular case are available to
you in the Accelerated case as well.
=back
@@ -2123,8 +2097,8 @@ references to the arrays to the constructor.
$lcm = List::Compare->new(\@Al, \@Bob, \@Carmen, \@Don, \@Ed);
-As with List::Compare's Regular case, should you not need to have
-a sorted list returned by a List::Compare method, you may achieve a
+As with List::Compare's Regular case, should you not need to have
+a sorted list returned by a List::Compare method, you may achieve a
speed boost by constructing the object with the unsorted option:
$lcm = List::Compare->new('-u', \@Al, \@Bob, \@Carmen, \@Don, \@Ed);
@@ -2135,7 +2109,7 @@ or
=item * Alternative Constructor
-You may use the 'single hashref' constructor format to build a List::Compare
+You may use the 'single hashref' constructor format to build a List::Compare
object to process three or more lists at once:
$lcm = List::Compare->new( {
@@ -2151,24 +2125,24 @@ or
=item * Multiple Mode Methods Analogous to Regular and Accelerated Mode Methods
-Each List::Compare method available in the Regular and Accelerated cases
-has an analogue in the Multiple case. However, the results produced
+Each List::Compare method available in the Regular and Accelerated cases
+has an analogue in the Multiple case. However, the results produced
usually require more careful specification.
-B<Note:> Certain of the following methods available in List::Compare's
-Multiple mode take optional numerical arguments where those numbers
-represent the index position of a particular list in the list of arguments
+B<Note:> Certain of the following methods available in List::Compare's
+Multiple mode take optional numerical arguments where those numbers
+represent the index position of a particular list in the list of arguments
passed to the constructor. To specify this index position correctly,
=over 4
=item *
-start the count at C<0> (as is customary with Perl array indices); and
+start the count at C<0> (as is customary with Perl array indices); and
=item *
-do I<not> count any unsorted option (C<'-u'> or C<'--unsorted'>) preceding
+do I<not> count any unsorted option (C<'-u'> or C<'--unsorted'>) preceding
the array references in the constructor's own argument list.
=back
@@ -2177,76 +2151,76 @@ Example:
$lcmex = List::Compare->new('--unsorted', \@alpha, \@beta, \@gamma);
-For the purpose of supplying a numerical argument to a method which
-optionally takes such an argument, C<'--unsorted'> is skipped, C<@alpha>
+For the purpose of supplying a numerical argument to a method which
+optionally takes such an argument, C<'--unsorted'> is skipped, C<@alpha>
is C<0>, C<@beta> is C<1>, and so forth.
=over 4
=item * C<get_intersection()>
-Get those items found in I<each> of the lists passed to the constructor
+Get those items found in I<each> of the lists passed to the constructor
(their intersection):
@intersection = $lcm->get_intersection;
=item * C<get_union()>
-Get those items found in I<any> of the lists passed to the constructor
+Get those items found in I<any> of the lists passed to the constructor
(their union):
@union = $lcm->get_union;
=item * C<get_unique()>
-To get those items which appear only in I<one particular list,> provide
-C<get_unique()> with that list's index position in the list of arguments
-passed to the constructor (not counting any C<'-u'> or C<'--unsorted'>
+To get those items which appear only in I<one particular list,> provide
+C<get_unique()> with that list's index position in the list of arguments
+passed to the constructor (not counting any C<'-u'> or C<'--unsorted'>
option).
-Example: C<@Carmen> has index position C<2> in the constructor's C<@_>.
-To get elements unique to C<@Carmen>:
+Example: C<@Carmen> has index position C<2> in the constructor's C<@_>.
+To get elements unique to C<@Carmen>:
@Lonly = $lcm->get_unique(2);
-If no index position is passed to C<get_unique()> it will default to 0
+If no index position is passed to C<get_unique()> it will default to 0
and report items unique to the first list passed to the constructor.
=item * C<get_complement()>
-To get those items which appear in any list I<other than one particular
-list,> provide C<get_complement()> with that list's index position in
-the list of arguments passed to the constructor (not counting any
+To get those items which appear in any list I<other than one particular
+list,> provide C<get_complement()> with that list's index position in
+the list of arguments passed to the constructor (not counting any
C<'-u'> or C<'--unsorted'> option).
-Example: C<@Don> has index position C<3> in the constructor's C<@_>.
-To get elements not found in C<@Don>:
+Example: C<@Don> has index position C<3> in the constructor's C<@_>.
+To get elements not found in C<@Don>:
@Ronly = $lcm->get_complement(3);
-If no index position is passed to C<get_complement()> it will default to
-0 and report items found in any list other than the first list passed
+If no index position is passed to C<get_complement()> it will default to
+0 and report items found in any list other than the first list passed
to the constructor.
=item * C<get_symmetric_difference()>
-Get those items each of which appears in I<only one> of the lists
+Get those items each of which appears in I<only one> of the lists
passed to the constructor (their symmetric_difference);
@LorRonly = $lcm->get_symmetric_difference;
=item * C<get_bag()>
-Make a bag of all items found in any list. The bag differs from the
-lists' union in that it holds as many copies of individual elements
+Make a bag of all items found in any list. The bag differs from the
+lists' union in that it holds as many copies of individual elements
as appear in the original lists.
@bag = $lcm->get_bag;
=item * Return reference instead of list
-An alternative approach to the above methods: If you do not immediately
-require an array as the return value of the method call, but simply need
+An alternative approach to the above methods: If you do not immediately
+require an array as the return value of the method call, but simply need
a I<reference> to an array, use one of the following parallel methods:
$intersection_ref = $lcm->get_intersection_ref;
@@ -2258,72 +2232,72 @@ a I<reference> to an array, use one of the following parallel methods:
=item * C<is_LsubsetR()>
-To determine whether one particular list is a subset of another list
-passed to the constructor, provide C<is_LsubsetR()> with the index
-position of the presumed subset (ignoring any unsorted option), followed
-by the index position of the presumed superset.
+To determine whether one particular list is a subset of another list
+passed to the constructor, provide C<is_LsubsetR()> with the index
+position of the presumed subset (ignoring any unsorted option), followed
+by the index position of the presumed superset.
Example: To determine whether C<@Ed> is a subset of C<@Carmen>, call:
$LR = $lcm->is_LsubsetR(4,2);
-A true value (C<1>) is returned if the left-hand list is a subset of the
+A true value (C<1>) is returned if the left-hand list is a subset of the
right-hand list; a false value (C<0>) is returned otherwise.
-If no arguments are passed, C<is_LsubsetR()> defaults to C<(0,1)> and
+If no arguments are passed, C<is_LsubsetR()> defaults to C<(0,1)> and
compares the first two lists passed to the constructor.
=item * C<is_LequivalentR()>
-To determine whether any two particular lists are equivalent to each
-other, provide C<is_LequivalentR> with their index positions in the
+To determine whether any two particular lists are equivalent to each
+other, provide C<is_LequivalentR> with their index positions in the
list of arguments passed to the constructor (ignoring any unsorted option).
Example: To determine whether C<@Don> and C<@Ed> are equivalent, call:
$eqv = $lcm->is_LequivalentR(3,4);
-A true value (C<1>) is returned if the lists are equivalent; a false value
-(C<0>) otherwise.
+A true value (C<1>) is returned if the lists are equivalent; a false value
+(C<0>) otherwise.
-If no arguments are passed, C<is_LequivalentR> defaults to C<(0,1)> and
+If no arguments are passed, C<is_LequivalentR> defaults to C<(0,1)> and
compares the first two lists passed to the constructor.
=item * C<is_LdisjointR()>
-To determine whether any two particular lists are disjoint from each other
-(I<i.e.,> have no members in common), provide C<is_LdisjointR> with their
-index positions in the list of arguments passed to the constructor
+To determine whether any two particular lists are disjoint from each other
+(I<i.e.,> have no members in common), provide C<is_LdisjointR> with their
+index positions in the list of arguments passed to the constructor
(ignoring any unsorted option).
Example: To determine whether C<@Don> and C<@Ed> are disjoint, call:
$disj = $lcm->is_LdisjointR(3,4);
-A true value (C<1>) is returned if the lists are equivalent; a false value
-(C<0>) otherwise.
+A true value (C<1>) is returned if the lists are equivalent; a false value
+(C<0>) otherwise.
-If no arguments are passed, C<is_LdisjointR> defaults to C<(0,1)> and
+If no arguments are passed, C<is_LdisjointR> defaults to C<(0,1)> and
compares the first two lists passed to the constructor.
=item * C<print_subset_chart()>
-Pretty-print a chart showing the subset relationships among the various
+Pretty-print a chart showing the subset relationships among the various
source lists:
$lcm->print_subset_chart;
=item * C<print_equivalence_chart()>
-Pretty-print a chart showing the equivalence relationships among the
+Pretty-print a chart showing the equivalence relationships among the
various source lists:
$lcm->print_equivalence_chart;
=item * C<is_member_which()>
-Determine in I<which> (if any) of the lists passed to the constructor a given
-string can be found. In list context, return a list of those indices in the
+Determine in I<which> (if any) of the lists passed to the constructor a given
+string can be found. In list context, return a list of those indices in the
constructor's argument list (ignoring any unsorted option) corresponding to i
lists holding the string being tested.
@@ -2333,12 +2307,12 @@ In the example above, C<@memb_arr> will be:
( 0 )
-because C<'abel'> is found only in C<@Al> which holds position C<0> in the
+because C<'abel'> is found only in C<@Al> which holds position C<0> in the
list of arguments passed to C<new()>.
=item * C<is_member_which_ref()>
-As with other List::Compare methods which return a list, you may wish the
+As with other List::Compare methods which return a list, you may wish the
above method returned a (scalar) reference to an array holding the list:
$memb_arr_ref = $lcm->is_member_which_ref('jerky');
@@ -2347,31 +2321,31 @@ In the example above, C<$memb_arr_ref> will be:
[ 3, 4 ]
-because C<'jerky'> is found in C<@Don> and C<@Ed>, which hold positions
+because C<'jerky'> is found in C<@Don> and C<@Ed>, which hold positions
C<3> and C<4>, respectively, in the list of arguments passed to C<new()>.
B<Note:> methods C<is_member_which()> and C<is_member_which_ref> test
-only one string at a time and hence take only one argument. To test more
+only one string at a time and hence take only one argument. To test more
than one string at a time see the next method, C<are_members_which()>.
=item * C<are_members_which()>
-Determine in C<which> (if any) of the lists passed to the constructor one or
-more given strings can be found. The strings to be tested are placed in an
+Determine in C<which> (if any) of the lists passed to the constructor one or
+more given strings can be found. The strings to be tested are placed in an
anonymous array, a reference to which is passed to the method.
- $memb_hash_ref =
+ $memb_hash_ref =
$lcm->are_members_which([ qw| abel baker fargo hilton zebra | ]);
-I<Note:> In versions of List::Compare prior to 0.25 (April 2004), the
-strings to be tested could be passed as a flat list. This is no longer
+I<Note:> In versions of List::Compare prior to 0.25 (April 2004), the
+strings to be tested could be passed as a flat list. This is no longer
possible; the argument must now be a reference to an anonymous array.
-The return value is a reference to a hash of arrays. The
-key for each element in this hash is the string being tested. Each element's
-value is a reference to an anonymous array whose elements are those indices in
-the constructor's argument list corresponding to lists holding the strings
-being tested.
+The return value is a reference to a hash of arrays. The
+key for each element in this hash is the string being tested. Each element's
+value is a reference to an anonymous array whose elements are those indices in
+the constructor's argument list corresponding to lists holding the strings
+being tested.
In the two examples above, C<$memb_hash_ref> will be:
@@ -2383,41 +2357,41 @@ In the two examples above, C<$memb_hash_ref> will be:
zebra => [ ],
};
-B<Note:> C<are_members_which()> can take more than one argument;
-C<is_member_which()> and C<is_member_which_ref()> each take only one argument.
-C<are_members_which()> returns a hash reference; the other methods return
-either a list or a reference to an array holding that list, depending on
+B<Note:> C<are_members_which()> can take more than one argument;
+C<is_member_which()> and C<is_member_which_ref()> each take only one argument.
+C<are_members_which()> returns a hash reference; the other methods return
+either a list or a reference to an array holding that list, depending on
context.
=item * C<is_member_any()>
-Determine whether a given string can be found in I<any> of the lists passed as
+Determine whether a given string can be found in I<any> of the lists passed as
arguments to the constructor.
$found = $lcm->is_member_any('abel');
-Return C<1> if a specified string can be found in I<any> of the lists
+Return C<1> if a specified string can be found in I<any> of the lists
and C<0> if not.
-In the example above, C<$found> will be C<1> because C<'abel'> is found in one
+In the example above, C<$found> will be C<1> because C<'abel'> is found in one
or more of the lists passed as arguments to C<new()>.
=item * C<are_members_any()>
-Determine whether a specified string or strings can be found in I<any> of the
-lists passed as arguments to the constructor. The strings to be tested are
-placed in an array (anonymous or named), a reference to which is passed to
+Determine whether a specified string or strings can be found in I<any> of the
+lists passed as arguments to the constructor. The strings to be tested are
+placed in an array (anonymous or named), a reference to which is passed to
the method.
$memb_hash_ref = $lcm->are_members_any([ qw| abel baker fargo hilton zebra | ]);
-I<Note:> In versions of List::Compare prior to 0.25 (April 2004), the
-strings to be tested could be passed as a flat list. This is no longer
+I<Note:> In versions of List::Compare prior to 0.25 (April 2004), the
+strings to be tested could be passed as a flat list. This is no longer
possible; the argument must now be a reference to an anonymous array.
-The return value is a reference to a hash where an element's key is the
-string being tested and the element's value is 1 if the string can be
-found in C<any> of the lists and 0 if not.
+The return value is a reference to a hash where an element's key is the
+string being tested and the element's value is 1 if the string can be
+found in C<any> of the lists and 0 if not.
In the two examples above, C<$memb_hash_ref> will be:
{
@@ -2428,7 +2402,7 @@ In the two examples above, C<$memb_hash_ref> will be:
zebra => 0,
};
-C<zebra>'s value will be C<0> because C<zebra> is not found in any of the
+C<zebra>'s value will be C<0> because C<zebra> is not found in any of the
lists passed as arguments to C<new()>.
=item * C<get_version()>
@@ -2445,23 +2419,23 @@ Return current List::Compare version number:
=item * C<get_nonintersection()>
-Get those items found in I<any> of the lists passed to the constructor which
-do I<not> appear in I<all> of the lists (I<i.e.,> all items except those found
+Get those items found in I<any> of the lists passed to the constructor which
+do I<not> appear in I<all> of the lists (I<i.e.,> all items except those found
in the intersection of the lists):
@nonintersection = $lcm->get_nonintersection;
=item * C<get_shared()>
-Get those items which appear in more than one of the lists passed to the
-constructor (I<i.e.,> all items except those found in their symmetric
+Get those items which appear in more than one of the lists passed to the
+constructor (I<i.e.,> all items except those found in their symmetric
difference);
@shared = $lcm->get_shared;
=item * C<get_nonintersection_ref()>
-If you only need a reference to an array as a return value rather than a
+If you only need a reference to an array as a return value rather than a
full array, use the following alternative methods:
$nonintersection_ref = $lcm->get_nonintersection_ref;
@@ -2469,8 +2443,8 @@ full array, use the following alternative methods:
=item * C<get_unique_all()>
-Get a reference to an array of array references where each of the interior
-arrays holds the list of those items I<unique> to the list passed to the
+Get a reference to an array of array references where each of the interior
+arrays holds the list of those items I<unique> to the list passed to the
constructor with the same index position.
$unique_all_ref = $lcm->get_unique_all();
@@ -2487,8 +2461,8 @@ In the example above, C<$unique_all_ref> will hold:
=item * C<get_complement_all()>
-Get a reference to an array of array references where each of the interior
-arrays holds the list of those items in the I<complement> to the list
+Get a reference to an array of array references where each of the interior
+arrays holds the list of those items in the I<complement> to the list
passed to the constructor with the same index position.
$complement_all_ref = $lcm->get_complement_all();
@@ -2513,9 +2487,9 @@ In the example above, C<$complement_all_ref> will hold:
=item * Constructor C<new()>
-If you are certain that you will only want the results of a single
-comparison among three or more lists, computation may be accelerated
-by passing C<'-a'> or C<'--accelerated> as the first argument to
+If you are certain that you will only want the results of a single
+comparison among three or more lists, computation may be accelerated
+by passing C<'-a'> or C<'--accelerated> as the first argument to
the constructor.
@Al = qw(abel abel baker camera delta edward fargo golfer);
@@ -2524,14 +2498,14 @@ the constructor.
@Don = qw(fargo icon jerky);
@Ed = qw(fargo icon icon jerky);
- $lcma = List::Compare->new('-a',
+ $lcma = List::Compare->new('-a',
\@Al, \@Bob, \@Carmen, \@Don, \@Ed);
-As with List::Compare's other cases, should you not need to have
-a sorted list returned by a List::Compare method, you may achieve a
+As with List::Compare's other cases, should you not need to have
+a sorted list returned by a List::Compare method, you may achieve a
speed boost by constructing the object with the unsorted option:
- $lcma = List::Compare->new('-u', '-a',
+ $lcma = List::Compare->new('-u', '-a',
\@Al, \@Bob, \@Carmen, \@Don, \@Ed);
or
@@ -2539,9 +2513,9 @@ or
$lcma = List::Compare->new('--unsorted', '--accelerated',
\@Al, \@Bob, \@Carmen, \@Don, \@Ed);
-As was the case with List::Compare's Multiple mode, do not count the
-unsorted option (C<'-u'> or C<'--unsorted'>) or the accelerated option
-(C<'-a'> or C<'--accelerated'>) when determining the index position of
+As was the case with List::Compare's Multiple mode, do not count the
+unsorted option (C<'-u'> or C<'--unsorted'>) or the accelerated option
+(C<'-a'> or C<'--accelerated'>) when determining the index position of
a particular list in the list of array references passed to the constructor.
Example:
@@ -2551,7 +2525,7 @@ Example:
=item * Alternative Constructor
-The 'single hashref' format may be used to construct a List::Compare
+The 'single hashref' format may be used to construct a List::Compare
object which calls for accelerated processing of three or more lists at once:
$lcmaex = List::Compare->new( {
@@ -2569,9 +2543,9 @@ or
=item * Methods
-For the purpose of supplying a numerical argument to a method which
-optionally takes such an argument, C<'--unsorted'> and C<'--accelerated>
-are skipped, C<@alpha> is C<0>, C<@beta> is C<1>, and so forth. To get a
+For the purpose of supplying a numerical argument to a method which
+optionally takes such an argument, C<'--unsorted'> and C<'--accelerated>
+are skipped, C<@alpha> is C<0>, C<@beta> is C<1>, and so forth. To get a
list of those items unique to C<@gamma>, you would call:
@gamma_only = $lcmaex->get_unique(2);
@@ -2584,10 +2558,10 @@ list of those items unique to C<@gamma>, you would call:
=item * When Seen-Hashes Are Already Available to You
-Suppose that in a particular Perl program, you had to do extensive munging of
-data from an external source and that, once you had correctly parsed a line
-of data, it was easier to assign that datum to a hash than to an array.
-More specifically, suppose that you used each datum as the key to an element
+Suppose that in a particular Perl program, you had to do extensive munging of
+data from an external source and that, once you had correctly parsed a line
+of data, it was easier to assign that datum to a hash than to an array.
+More specifically, suppose that you used each datum as the key to an element
of a lookup table in the form of a I<seen-hash>:
my %Llist = (
@@ -2610,13 +2584,13 @@ of a lookup table in the form of a I<seen-hash>:
hilton => 1,
);
-In other words, suppose it was more convenient to compute a lookup table
+In other words, suppose it was more convenient to compute a lookup table
I<implying> a list than to compute that list explicitly.
-Since in almost all cases List::Compare takes the elements in the arrays
-passed to its constructor and I<internally> assigns them to elements in a
-seen-hash, why shouldn't you be able to pass (references to) seen-hashes
-I<directly> to the constructor and avoid unnecessary array
+Since in almost all cases List::Compare takes the elements in the arrays
+passed to its constructor and I<internally> assigns them to elements in a
+seen-hash, why shouldn't you be able to pass (references to) seen-hashes
+I<directly> to the constructor and avoid unnecessary array
assignments before the constructor is called?
=item * Constructor C<new()>
@@ -2627,7 +2601,7 @@ You can now do so:
=item * Methods
-I<All> of List::Compare's output methods are supported I<without further
+I<All> of List::Compare's output methods are supported I<without further
modification> when references to seen-hashes are passed to the constructor.
@intersection = $lcsh->get_intersection;
@@ -2661,13 +2635,13 @@ modification> when references to seen-hashes are passed to the constructor.
=item * Accelerated Mode and Seen-Hashes
-To accelerate processing when you want only a single comparison among two or
-more lists, you can pass C<'-a'> or C<'--accelerated> to the constructor
+To accelerate processing when you want only a single comparison among two or
+more lists, you can pass C<'-a'> or C<'--accelerated> to the constructor
before passing references to seen-hashes.
$lcsha = List::Compare->new('-a', \%Llist, \%Rlist);
-To compare three or more lists simultaneously, pass three or more references
+To compare three or more lists simultaneously, pass three or more references
to seen-hashes. Thus,
$lcshm = List::Compare->new(\%Alpha, \%Beta, \%Gamma);
@@ -2676,20 +2650,20 @@ will generate meaningful comparisons of three or more lists simultaneously.
=item * Unsorted Results and Seen-Hashes
-If you do not need sorted lists returned, pass C<'-u'> or C<--unsorted> to the
+If you do not need sorted lists returned, pass C<'-u'> or C<--unsorted> to the
constructor before passing references to seen-hashes.
$lcshu = List::Compare->new('-u', \%Llist, \%Rlist);
$lcshau = List::Compare->new('-u', '-a', \%Llist, \%Rlist);
$lcshmu = List::Compare->new('--unsorted', \%Alpha, \%Beta, \%Gamma);
-As was true when we were using List::Compare's Multiple and Multiple Accelerated
-modes, do not count any unsorted or accelerated option when determining the
+As was true when we were using List::Compare's Multiple and Multiple Accelerated
+modes, do not count any unsorted or accelerated option when determining the
array index of a particular seen-hash reference passed to the constructor.
=item * Alternative Constructor
-The 'single hashref' form of constructor is also available to build
+The 'single hashref' form of constructor is also available to build
List::Compare objects where seen-hashes are used as arguments:
$lcshu = List::Compare->new( {
@@ -2710,33 +2684,33 @@ List::Compare objects where seen-hashes are used as arguments:
=back
-=head1 DISCUSSION: Principles
+=head1 DISCUSSION: Principles
=head2 General Comments
-List::Compare is an object-oriented implementation of very common Perl
+List::Compare is an object-oriented implementation of very common Perl
code (see "History, References and Development" below) used to
-determine interesting relationships between two or more lists at a time.
+determine interesting relationships between two or more lists at a time.
A List::Compare object is created and automatically computes the values
needed to supply List::Compare methods with appropriate results. In the
current implementation List::Compare methods will return new lists
-containing the items found in any designated list alone (unique), any list
-other than a designated list (complement), the intersection and union of
+containing the items found in any designated list alone (unique), any list
+other than a designated list (complement), the intersection and union of
all lists and so forth. List::Compare also has (a) methods to return Boolean
-values indicating whether one list is a subset of another and whether any
-two lists are equivalent to each other (b) methods to pretty-print very
-simple charts displaying the subset and equivalence relationships among
+values indicating whether one list is a subset of another and whether any
+two lists are equivalent to each other (b) methods to pretty-print very
+simple charts displaying the subset and equivalence relationships among
lists.
-Except for List::Compare's C<get_bag()> method, B<multiple instances of
-an element in a given list count only once with
-respect to computing the intersection, union, etc. of the two lists.> In
-particular, List::Compare considers two lists as equivalent if each element
-of the first list can be found in the second list and I<vice versa>.
-'Equivalence' in this usage takes no note of the frequency with which
-elements occur in either list or their order within the lists. List::Compare
-asks the question: I<Did I see this item in this list at all?> Only when
-you use C<List::Compare::get_bag()> to compute a bag holding the two lists do you
+Except for List::Compare's C<get_bag()> method, B<multiple instances of
+an element in a given list count only once with
+respect to computing the intersection, union, etc. of the two lists.> In
+particular, List::Compare considers two lists as equivalent if each element
+of the first list can be found in the second list and I<vice versa>.
+'Equivalence' in this usage takes no note of the frequency with which
+elements occur in either list or their order within the lists. List::Compare
+asks the question: I<Did I see this item in this list at all?> Only when
+you use C<List::Compare::get_bag()> to compute a bag holding the two lists do you
ask the question: How many times did this item occur in this list?
=head2 List::Compare Modes
@@ -2749,145 +2723,145 @@ In its current implementation List::Compare has four modes of operation.
Regular Mode
-List::Compare's Regular mode is based on List::Compare v0.11 -- the first
-version of List::Compare released to CPAN (June 2002). It compares only
-two lists at a time. Internally, its initializer does all computations
-needed to report any desired comparison and its constructor stores the
-results of these computations. Its public methods merely report these
+List::Compare's Regular mode is based on List::Compare v0.11 -- the first
+version of List::Compare released to CPAN (June 2002). It compares only
+two lists at a time. Internally, its initializer does all computations
+needed to report any desired comparison and its constructor stores the
+results of these computations. Its public methods merely report these
results.
-This approach has the advantage that if you need to examine more
-than one form of comparison between two lists (I<e.g.,> the union,
-intersection and symmetric difference of two lists), the comparisons are
-pre-calculated. This approach is efficient because certain types of
-comparison presuppose that other types have already been calculated.
-For example, to calculate the symmetric difference of two lists, one must
+This approach has the advantage that if you need to examine more
+than one form of comparison between two lists (I<e.g.,> the union,
+intersection and symmetric difference of two lists), the comparisons are
+pre-calculated. This approach is efficient because certain types of
+comparison presuppose that other types have already been calculated.
+For example, to calculate the symmetric difference of two lists, one must
first determine the items unique to each of the two lists.
=item *
Accelerated Mode
-The current implementation of List::Compare offers you the option of
-getting even faster results I<provided> that you only need the
-result from a I<single> form of comparison between two lists. (I<e.g.,> only
-the union -- nothing else). In the Accelerated mode, List::Compare's
-initializer does no computation and its constructor stores only references
-to the two source lists. All computation needed to report results is
+The current implementation of List::Compare offers you the option of
+getting even faster results I<provided> that you only need the
+result from a I<single> form of comparison between two lists. (I<e.g.,> only
+the union -- nothing else). In the Accelerated mode, List::Compare's
+initializer does no computation and its constructor stores only references
+to the two source lists. All computation needed to report results is
deferred to the method calls.
-The user selects this approach by passing the option flag C<'-a'> to the
-constructor before passing references to the two source lists.
-List::Compare notes the option flag and silently switches into Accelerated
-mode. From the perspective of the user, there is no further difference in
+The user selects this approach by passing the option flag C<'-a'> to the
+constructor before passing references to the two source lists.
+List::Compare notes the option flag and silently switches into Accelerated
+mode. From the perspective of the user, there is no further difference in
the code or in the results.
-Benchmarking suggests that List::Compare's Accelerated mode (a) is faster
-than its Regular mode when only one comparison is requested; (b) is about as
-fast as Regular mode when two comparisons are requested; and (c) becomes
-considerably slower than Regular mode as each additional comparison above two
+Benchmarking suggests that List::Compare's Accelerated mode (a) is faster
+than its Regular mode when only one comparison is requested; (b) is about as
+fast as Regular mode when two comparisons are requested; and (c) becomes
+considerably slower than Regular mode as each additional comparison above two
is requested.
=item *
Multiple Mode
-List::Compare now offers the possibility of comparing three or more lists at
-a time. Simply store the extra lists in arrays and pass references to those
-arrays to the constructor. List::Compare detects that more than two lists
+List::Compare now offers the possibility of comparing three or more lists at
+a time. Simply store the extra lists in arrays and pass references to those
+arrays to the constructor. List::Compare detects that more than two lists
have been passed to the constructor and silently switches into Multiple mode.
-As described in the Synopsis above, comparing more than two lists at a time
-offers you a wider, more complex palette of comparison methods.
-Individual items may appear in just one source list, in all the source lists,
-or in some number of lists between one and all. The meaning of 'union',
-'intersection' and 'symmetric difference' is conceptually unchanged
-when you move to multiple lists because these are properties of all the lists
-considered together. In contrast, the meaning of 'unique', 'complement',
-'subset' and 'equivalent' changes because these are properties of one list
+As described in the Synopsis above, comparing more than two lists at a time
+offers you a wider, more complex palette of comparison methods.
+Individual items may appear in just one source list, in all the source lists,
+or in some number of lists between one and all. The meaning of 'union',
+'intersection' and 'symmetric difference' is conceptually unchanged
+when you move to multiple lists because these are properties of all the lists
+considered together. In contrast, the meaning of 'unique', 'complement',
+'subset' and 'equivalent' changes because these are properties of one list
compared with another or with all the other lists combined.
-List::Compare takes this complexity into account by allowing you to pass
-arguments to the public methods requesting results with respect to a specific
-list (for C<get_unique()> and C<get_complement()>) or a specific pair of lists
+List::Compare takes this complexity into account by allowing you to pass
+arguments to the public methods requesting results with respect to a specific
+list (for C<get_unique()> and C<get_complement()>) or a specific pair of lists
(for C<is_LsubsetR()> and C<is_LequivalentR()>).
-List::Compare further takes this complexity into account by offering the
-new methods C<get_shared()> and C<get_nonintersection()> described in the
+List::Compare further takes this complexity into account by offering the
+new methods C<get_shared()> and C<get_nonintersection()> described in the
Synopsis above.
=item *
Multiple Accelerated Mode
-Beginning with version 0.25, introduced in April 2004, List::Compare
-offers the possibility of accelerated computation of a single comparison
-among three or more lists at a time. Simply store the extra lists in
-arrays and pass references to those arrays to the constructor preceded by
-the C<'-a'> argument as was done with the simple (two lists only)
-accelerated mode. List::Compare detects that more than two lists have been
-passed to the constructor and silently switches into Multiple Accelerated
+Beginning with version 0.25, introduced in April 2004, List::Compare
+offers the possibility of accelerated computation of a single comparison
+among three or more lists at a time. Simply store the extra lists in
+arrays and pass references to those arrays to the constructor preceded by
+the C<'-a'> argument as was done with the simple (two lists only)
+accelerated mode. List::Compare detects that more than two lists have been
+passed to the constructor and silently switches into Multiple Accelerated
mode.
=item *
Unsorted Option
-When List::Compare is used to return lists representing various comparisons
-of two or more lists (I<e.g.>, the lists' union or intersection), the lists
-returned are, by default, sorted using Perl's default C<sort> mode:
-ASCII-betical sorting. Sorting produces results which are more easily
+When List::Compare is used to return lists representing various comparisons
+of two or more lists (I<e.g.>, the lists' union or intersection), the lists
+returned are, by default, sorted using Perl's default C<sort> mode:
+ASCII-betical sorting. Sorting produces results which are more easily
human-readable but may entail a performance cost.
-Should you not need sorted results, you can avoid the potential
-performance cost by calling List::Compare's constructor using the unsorted
-option. This is done by calling C<'-u'> or C<'--unsorted'> as the first
-argument passed to the constructor, I<i.e.>, as an argument called before
+Should you not need sorted results, you can avoid the potential
+performance cost by calling List::Compare's constructor using the unsorted
+option. This is done by calling C<'-u'> or C<'--unsorted'> as the first
+argument passed to the constructor, I<i.e.>, as an argument called before
any references to lists are passed to the constructor.
-Note that if are calling List::Compare in the Accelerated or Multiple
-Accelerated mode I<and> wish to have the lists returned in unsorted order,
-you I<first> pass the argument for the unsorted option
-(C<'-u'> or C<'--unsorted'>) and I<then> pass the argument for the
+Note that if are calling List::Compare in the Accelerated or Multiple
+Accelerated mode I<and> wish to have the lists returned in unsorted order,
+you I<first> pass the argument for the unsorted option
+(C<'-u'> or C<'--unsorted'>) and I<then> pass the argument for the
Accelerated mode (C<'-a'> or C<'--accelerated'>).
=back
=head2 Miscellaneous Methods
-It would not really be appropriate to call C<get_shared()> and
-C<get_nonintersection()> in Regular or Accelerated mode since they are
-conceptually based on the notion of comparing more than two lists at a time.
-However, there is always the possibility that a user may be comparing only two
-lists (accelerated or not) and may accidentally call one of those two methods.
-To prevent fatal run-time errors and to caution you to use a more
-appropriate method, these two methods are defined for Regular and Accelerated
-modes so as to return suitable results but also generate a carp message that
+It would not really be appropriate to call C<get_shared()> and
+C<get_nonintersection()> in Regular or Accelerated mode since they are
+conceptually based on the notion of comparing more than two lists at a time.
+However, there is always the possibility that a user may be comparing only two
+lists (accelerated or not) and may accidentally call one of those two methods.
+To prevent fatal run-time errors and to caution you to use a more
+appropriate method, these two methods are defined for Regular and Accelerated
+modes so as to return suitable results but also generate a carp message that
advise you to re-code.
-Similarly, the method C<is_RsubsetL()> is appropriate for the Regular and
-Accelerated modes but is not really appropriate for Multiple mode. As a
-defensive maneuver, it has been defined for Multiple mode so as to return
-suitable results but also to generate a carp message that advises you to
+Similarly, the method C<is_RsubsetL()> is appropriate for the Regular and
+Accelerated modes but is not really appropriate for Multiple mode. As a
+defensive maneuver, it has been defined for Multiple mode so as to return
+suitable results but also to generate a carp message that advises you to
re-code.
-In List::Compare v0.11 and earlier, the author provided aliases for various
-methods based on the supposition that the source lists would be referred to as
-'A' and 'B'. Now that you can compare more than two lists at a time, the author
-feels that it would be more appropriate to refer to the elements of two-argument
-lists as the left-hand and right-hand elements. Hence, we are discouraging the
-use of methods such as C<get_Aonly()>, C<get_Bonly()> and C<get_AorBonly()> as
-aliases for C<get_unique()>, C<get_complement()> and
-C<get_symmetric_difference()>. However, to guarantee backwards compatibility
-for the vast audience of Perl programmers using earlier versions of
-List::Compare (all 10e1 of you) these and similar methods for subset
+In List::Compare v0.11 and earlier, the author provided aliases for various
+methods based on the supposition that the source lists would be referred to as
+'A' and 'B'. Now that you can compare more than two lists at a time, the author
+feels that it would be more appropriate to refer to the elements of two-argument
+lists as the left-hand and right-hand elements. Hence, we are discouraging the
+use of methods such as C<get_Aonly()>, C<get_Bonly()> and C<get_AorBonly()> as
+aliases for C<get_unique()>, C<get_complement()> and
+C<get_symmetric_difference()>. However, to guarantee backwards compatibility
+for the vast audience of Perl programmers using earlier versions of
+List::Compare (all 10e1 of you) these and similar methods for subset
relationships are still defined.
=head2 List::Compare::SeenHash Discontinued Beginning with Version 0.26
-Prior to v0.26, introduced April 11, 2004, if a user wished to pass
-references to seen-hashes to List::Compare's constructor rather than
-references to arrays, he or she had to call a different, parallel module:
+Prior to v0.26, introduced April 11, 2004, if a user wished to pass
+references to seen-hashes to List::Compare's constructor rather than
+references to arrays, he or she had to call a different, parallel module:
List::Compare::SeenHash. The code for that looked like this:
use List::Compare::SeenHash;
@@ -2914,46 +2888,46 @@ List::Compare::SeenHash. The code for that looked like this:
my $lcsh = List::Compare::SeenHash->new(\%Llist, \%Rlist);
-B<List::Compare::SeenHash is deprecated beginning with version 0.26.> All
-its functionality (and more) has been implemented in List::Compare itself,
-since a user can now pass I<either> a series of array references I<or> a
+B<List::Compare::SeenHash is deprecated beginning with version 0.26.> All
+its functionality (and more) has been implemented in List::Compare itself,
+since a user can now pass I<either> a series of array references I<or> a
series of seen-hash references to List::Compare's constructor.
-To simplify future maintenance of List::Compare, List::Compare::SeenHash.pm
-will no longer be distributed with List::Compare, nor will the files in the
+To simplify future maintenance of List::Compare, List::Compare::SeenHash.pm
+will no longer be distributed with List::Compare, nor will the files in the
test suite which tested List::Compare::SeenHash upon installation be distributed.
-Should you still need List::Compare::SeenHash, use version 0.25 from CPAN, or
-simply edit your Perl programs which used List::Compare::SeenHash. Those
-scripts may be edited quickly with, for example, this editing command in
+Should you still need List::Compare::SeenHash, use version 0.25 from CPAN, or
+simply edit your Perl programs which used List::Compare::SeenHash. Those
+scripts may be edited quickly with, for example, this editing command in
Unix text editor F<vi>:
:1,$s/List::Compare::SeenHash/List::Compare/gc
=head2 A Non-Object-Oriented Interface: List::Compare::Functional
-Version 0.21 of List::Compare introduced List::Compare::Functional,
-a functional (I<i.e.>, non-object-oriented) interface to list comparison
-functions. List::Compare::Functional supports the same functions currently
-supported by List::Compare. It works similar to List::Compare's Accelerated
-and Multiple Accelerated modes (described above), bit it does not
-require use of the C<'-a'> flag in the function call.
-List::Compare::Functional will return unsorted comparisons of two lists by
-passing C<'-u'> or C<'--unsorted'> as the first argument to the function.
-Please see the documentation for List::Compare::Functional to learn how to
+Version 0.21 of List::Compare introduced List::Compare::Functional,
+a functional (I<i.e.>, non-object-oriented) interface to list comparison
+functions. List::Compare::Functional supports the same functions currently
+supported by List::Compare. It works similar to List::Compare's Accelerated
+and Multiple Accelerated modes (described above), bit it does not
+require use of the C<'-a'> flag in the function call.
+List::Compare::Functional will return unsorted comparisons of two lists by
+passing C<'-u'> or C<'--unsorted'> as the first argument to the function.
+Please see the documentation for List::Compare::Functional to learn how to
import its functions into your main package.
=head1 ASSUMPTIONS AND QUALIFICATIONS
-The program was created with Perl 5.6. The use of I<h2xs> to prepare
+The program was created with Perl 5.6. The use of I<h2xs> to prepare
the module's template installed C<require 5.005_62;> at the top of the
-module. This has been commented out in the actual module as the code
-appears to be compatible with earlier versions of Perl; how earlier the
-author cannot say. In particular, the author would like the module to
-be installable on older versions of MacPerl. As is, the author has
-successfully installed the module on Linux, Windows 9x and Windows 2000.
-See L<http://testers.cpan.org/show/List-Compare.html> for
-a list of other systems on which this version of List::Compare has been
+module. This has been commented out in the actual module as the code
+appears to be compatible with earlier versions of Perl; how earlier the
+author cannot say. In particular, the author would like the module to
+be installable on older versions of MacPerl. As is, the author has
+successfully installed the module on Linux, Windows 9x and Windows 2000.
+See L<http://testers.cpan.org/show/List-Compare.html> for
+a list of other systems on which this version of List::Compare has been
tested and installed.
=head1 HISTORY, REFERENCES AND DEVELOPMENT
@@ -2962,27 +2936,27 @@ tested and installed.
List::Compare is based on code presented by Tom Christiansen & Nathan
Torkington in I<Perl Cookbook> L<http://www.oreilly.com/catalog/cookbook/>
-(a.k.a. the 'Ram' book), O'Reilly & Associates, 1998, Recipes 4.7 and 4.8.
+(a.k.a. the 'Ram' book), O'Reilly & Associates, 1998, Recipes 4.7 and 4.8.
Similar code is presented in the Camel book: I<Programming Perl>, by Larry
-Wall, Tom Christiansen, Jon Orwant.
+Wall, Tom Christiansen, Jon Orwant.
L<http://www.oreilly.com/catalog/pperl3/>, 3rd ed, O'Reilly & Associates,
2000. The list comparison code is so basic and Perlish that I suspect it
-may have been written by Larry himself at the dawn of Perl time. The
+may have been written by Larry himself at the dawn of Perl time. The
C<get_bag()> method was inspired by Jarkko Hietaniemi's Set::Bag module
and Daniel Berger's Set::Array module, both available on CPAN.
-List::Compare's original objective was simply to put this code in a modular,
-object-oriented framework. That framework, not surprisingly, is taken mostly
-from Damian Conway's I<Object Oriented Perl>
+List::Compare's original objective was simply to put this code in a modular,
+object-oriented framework. That framework, not surprisingly, is taken mostly
+from Damian Conway's I<Object Oriented Perl>
L<http://www.manning.com/Conway/index.html>, Manning Publications, 2000.
-With the addition of the Accelerated, Multiple and Multiple Accelerated
-modes, List::Compare expands considerably in both size and capabilities.
-Nonetheless, Tom and Nat's I<Cookbook> code still lies at its core:
-the use of hashes as look-up tables to record elements seen in lists.
-Please note: List::Compare is not concerned with any concept of 'equality'
-among lists which hinges upon the frequency with which, or the order in
-which, elements appear in the lists to be compared. If this does not
+With the addition of the Accelerated, Multiple and Multiple Accelerated
+modes, List::Compare expands considerably in both size and capabilities.
+Nonetheless, Tom and Nat's I<Cookbook> code still lies at its core:
+the use of hashes as look-up tables to record elements seen in lists.
+Please note: List::Compare is not concerned with any concept of 'equality'
+among lists which hinges upon the frequency with which, or the order in
+which, elements appear in the lists to be compared. If this does not
meet your needs, you should look elsewhere or write your own module.
=head2 The Inspiration
@@ -2991,66 +2965,73 @@ I realized the usefulness of putting the list comparison code into a
module while preparing an introductory level Perl course given at the New
School University's Computer Instruction Center in April-May 2002. I was
comparing lists left and right. When I found myself writing very similar
-functions in different scripts, I knew a module was lurking somewhere.
-I learned the truth of the mantra ''Repeated Code is a Mistake'' from a
-2001 talk by Mark-Jason Dominus L<http://perl.plover.com/> to the New York
-Perlmongers L<http://ny.pm.org/>.
-See L<http://www.perl.com/pub/a/2000/11/repair3.html>.
-
-The first public presentation of this module took place at Perl Seminar
-New York L<http://groups.yahoo.com/group/perlsemny> on May 21, 2002.
-Comments and suggestions were provided there and since by Glenn Maciag,
+functions in different scripts, I knew a module was lurking somewhere.
+I learned the truth of the mantra ''Repeated Code is a Mistake'' from a
+2001 talk by Mark-Jason Dominus L<http://perl.plover.com/> to the New York
+Perlmongers L<http://ny.pm.org/>.
+See L<http://www.perl.com/pub/a/2000/11/repair3.html>.
+
+The first public presentation of this module took place at Perl Seminar
+New York L<http://groups.yahoo.com/group/perlsemny> on May 21, 2002.
+Comments and suggestions were provided there and since by Glenn Maciag,
Gary Benson, Josh Rabinowitz, Terrence Brannon and Dave Cross.
-The placement in the installation tree of Test::ListCompareSpecial came
-as a result of a question answered by Michael Graham in his talk
-''Test::More to Test::Extreme'' given at Yet Another Perl Conference::Canada
-in Ottawa, Ontario, on May 16, 2003.
+The placement in the installation tree of Test::ListCompareSpecial came
+as a result of a question answered by Michael Graham in his talk
+''Test::More to Test::Extreme'' given at Yet Another Perl Conference::Canada
+in Ottawa, Ontario, on May 16, 2003.
-In May-June 2003, Glenn Maciag made valuable suggestions which led to
-changes in method names and documentation in v0.20.
+In May-June 2003, Glenn Maciag made valuable suggestions which led to
+changes in method names and documentation in v0.20.
-Another presentation at Perl Seminar New York in
-October 2003 prompted me to begin planning List::Compare::Functional.
+Another presentation at Perl Seminar New York in
+October 2003 prompted me to begin planning List::Compare::Functional.
-In a November 2003 Perl Seminar New York presentation, Ben Holtzman
-discussed the performance costs entailed in Perl's C<sort> function.
-This led me to ask, ''Why should a user of List::Compare pay this performance
-cost if he or she doesn't need a human-readable list as a result (as
-would be the case if the list returned were used as the input into some
-other function)?'' This led to the development of List::Compare's
+In a November 2003 Perl Seminar New York presentation, Ben Holtzman
+discussed the performance costs entailed in Perl's C<sort> function.
+This led me to ask, ''Why should a user of List::Compare pay this performance
+cost if he or she doesn't need a human-readable list as a result (as
+would be the case if the list returned were used as the input into some
+other function)?'' This led to the development of List::Compare's
unsorted option.
-An April 2004 offer by Kevin Carlson to write an article for I<The Perl Journal>
-(L<http://tpj.com>) led me to re-think whether a separate module
-(the former List::Compare::SeenHash) was truly needed when a user wanted
-to provide the constructor with references to seen-hashes rather than
-references to arrays. Since I had already adapted List::Compare::Functional
-to accept both kinds of arguments, I adapted List::Compare in the same
-manner. This meant that List::Compare::SeenHash and its related installation
+An April 2004 offer by Kevin Carlson to write an article for I<The Perl Journal>
+(L<http://tpj.com>) led me to re-think whether a separate module
+(the former List::Compare::SeenHash) was truly needed when a user wanted
+to provide the constructor with references to seen-hashes rather than
+references to arrays. Since I had already adapted List::Compare::Functional
+to accept both kinds of arguments, I adapted List::Compare in the same
+manner. This meant that List::Compare::SeenHash and its related installation
tests could be deprecated and deleted from the CPAN distribution.
-A remark by David H. Adler at a New York Perlmongers meeting in April 2004
-led me to develop the 'single hashref' alternative constructor format,
+A remark by David H. Adler at a New York Perlmongers meeting in April 2004
+led me to develop the 'single hashref' alternative constructor format,
introduced in version 0.29 the following month.
-Presentations at two different editions of Yet Another Perl Conference (YAPC)
-inspired the development of List::Compare versions 0.30 and 0.31. I was
-selected to give a talk on List::Compare at YAPC::NA::2004 in Buffalo. This
-spurred me to improve certain aspects of the documentation. Version 0.31
-owes its inspiration to one talk at the Buffalo YAPC and one earlier talk at
-YAPC::EU::2003 in Paris. In Paris I heard Paul Johnson speak on his CPAN
-module Devel::Cover and on coverage analysis more generally. That material
-was over my head at that time, but in Buffalo I heard Andy Lester discuss
-Devel::Cover as part of his discussion of testing and of the Phalanx project
-(L<http://qa.perl.org/phalanx>). This time I got it, and when I returned
-from Buffalo I applied Devel::Cover to List::Compare and wrote additional tests
-to improve its subroutine and statement coverage. In addition, I added two
-new methods, C<get_unique_all> and C<get_complement_all>. In writing these
-two methods, I followed a model of test-driven development much more so than
-in earlier versions of List::Compare and my other CPAN modules. The result?
+Presentations at two different editions of Yet Another Perl Conference (YAPC)
+inspired the development of List::Compare versions 0.30 and 0.31. I was
+selected to give a talk on List::Compare at YAPC::NA::2004 in Buffalo. This
+spurred me to improve certain aspects of the documentation. Version 0.31
+owes its inspiration to one talk at the Buffalo YAPC and one earlier talk at
+YAPC::EU::2003 in Paris. In Paris I heard Paul Johnson speak on his CPAN
+module Devel::Cover and on coverage analysis more generally. That material
+was over my head at that time, but in Buffalo I heard Andy Lester discuss
+Devel::Cover as part of his discussion of testing and of the Phalanx project
+(L<http://qa.perl.org/phalanx>). This time I got it, and when I returned
+from Buffalo I applied Devel::Cover to List::Compare and wrote additional tests
+to improve its subroutine and statement coverage. In addition, I added two
+new methods, C<get_unique_all> and C<get_complement_all>. In writing these
+two methods, I followed a model of test-driven development much more so than
+in earlier versions of List::Compare and my other CPAN modules. The result?
List::Compare's test suite grew by over 3300 tests to nearly 23,000 tests.
+At the Second New York Perl Hackathon (May 02 2015), a project was created to
+request performance improvements in certain List::Compare functions
+(L<https://github.com/nyperlmongers/nyperlhackathon2015/wiki/List-Compare-Performance-Improvements>).
+Hackathon participant Michael Rawson submitted a pull request with changes to
+List::Compare::Base::_Auxiliary. After these revisions were benchmarked, a
+patch embodying the pull request was accepted, leading to CPAN version 0.53.
+
=head2 If You Like List::Compare, You'll Love ...
While preparing this module for distribution via CPAN, I had occasion to
@@ -3058,7 +3039,7 @@ study a number of other modules already available on CPAN. Each of these
modules is more sophisticated than List::Compare -- which is not surprising
since all that List::Compare originally aspired to do was to avoid typing
Cookbook code repeatedly. Here is a brief description of the features of
-these modules. (B<Warning:> The following discussion is only valid as
+these modules. (B<Warning:> The following discussion is only valid as
of June 2002. Some of these modules may have changed since then.)
=over 4
@@ -3069,13 +3050,13 @@ Algorithm::Diff - Compute 'intelligent' differences between two files/lists
(L<http://search.cpan.org/dist/Algorithm-Diff/>)
Algorithm::Diff is a sophisticated module originally written by Mark-Jason
-Dominus, later maintained by Ned Konz, now maintained by Tye McQueen. Think of
+Dominus, later maintained by Ned Konz, now maintained by Tye McQueen. Think of
the Unix C<diff> utility and you're on the right track. Algorithm::Diff
-exports
-methods such as C<diff>, which ''computes the smallest set of additions and
-deletions necessary to turn the first sequence into the second, and returns a
-description of these changes.'' Algorithm::Diff is mainly concerned with the
-sequence of elements within two lists. It does not export functions for
+exports
+methods such as C<diff>, which ''computes the smallest set of additions and
+deletions necessary to turn the first sequence into the second, and returns a
+description of these changes.'' Algorithm::Diff is mainly concerned with the
+sequence of elements within two lists. It does not export functions for
intersection, union, subset status, etc.
=item *
@@ -3104,21 +3085,21 @@ returns the lowest numerical value in a list; the C<max> function returns
the highest value; and so forth. List::Compare differs from List::Util in
that it is object-oriented and that it works on two strings at a time
rather than just one -- but it aims to be as simple and useful as
-List::Util. List::Util will be included in the standard Perl
+List::Util. List::Util will be included in the standard Perl
distribution as of Perl 5.8.0.
-Lists::Util (L<http://search.cpan.org/dist/List-MoreUtils/>),
+Lists::Util (L<http://search.cpan.org/dist/List-MoreUtils/>),
by Tassilo von Parseval, building on code by Terrence Brannon, provides
-methods
+methods
which extend List::Util's functionality.
=item *
-Quantum::Superpositions
-(L<http://search.cpan.org/dist/Quantum-Superpositions/>),
-originally by Damian Conway, now maintained by Steven Lembark is useful if, in
+Quantum::Superpositions
+(L<http://search.cpan.org/dist/Quantum-Superpositions/>),
+originally by Damian Conway, now maintained by Steven Lembark is useful if, in
addition to comparing lists, you need to emulate quantum supercomputing as
-well.
+well.
Not for the eigen-challenged.
=item *
@@ -3134,8 +3115,8 @@ has methods to return the intersection, union, difference and symmetric
difference of two sets, as well as methods to return items unique to a
first set and complementary to it in a second set. It has methods for
reporting considerably more variants on subset status than does
-List::Compare. However, benchmarking suggests that List::Compare, at
-least in Regular mode, is considerably faster than Set::Scalar for those
+List::Compare. However, benchmarking suggests that List::Compare, at
+least in Regular mode, is considerably faster than Set::Scalar for those
comparison methods which List::Compare makes available.
Set::Bag enables one to deal more flexibly with the situation in which one
@@ -3155,29 +3136,42 @@ you must first install the Want module, also available on CPAN.
=back
+=head1 ADDITIONAL CONTRIBUTORS
+
+=over 4
+
+=item * Syohei YOSHIDA
+
+Pull request accepted May 22 2015.
+
+=item * Paulo Custodio
+
+Pull request accepted June 07 2015, correcting errors in C<_subset_subengine()>.
+
+=back
+
=head1 BUGS
-There are no bug reports outstanding on List::Compare as of the most recent
+There are no bug reports outstanding on List::Compare as of the most recent
CPAN upload date of this distribution.
=head1 SUPPORT
-Support for List::Compare is now provided by mailing list:
-L<http://thenceforward.net/cgi-bin/mailman/listinfo/list-compare>.
-
-Please report any bugs by mail to C<bug-ExtUtils-ModuleMaker@rt.cpan.org>
+Please report any bugs by mail to C<bug-List-Compare@rt.cpan.org>
or through the web interface at L<http://rt.cpan.org>.
=head1 AUTHOR
-James E. Keenan (jkeenan@cpan.org). When sending correspondence, please
+James E. Keenan (jkeenan@cpan.org). When sending correspondence, please
include 'List::Compare' or 'List-Compare' in your subject line.
-Creation date: May 20, 2002. Last modification date: June 07, 2008.
+Creation date: May 20, 2002. Last modification date: June 07 2015.
+
+Development repository: L<https://github.com/jkeenan/list-compare>
=head1 COPYRIGHT
-Copyright (c) 2002-06 James E. Keenan. United States. All rights reserved.
+Copyright (c) 2002-15 James E. Keenan. United States. All rights reserved.
This is free software and may be distributed under the same terms as Perl
itself.
@@ -3204,5 +3198,5 @@ FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
-=cut
+=cut
@@ -1,5 +1,5 @@
# perl
-#$Id: 01_oo_lists_dual_reg_sorted.t 1309 2008-06-01 00:47:38Z jimk $
+#$Id$
# 01_oo_lists_dual_reg_sorted.t
use strict;
use Test::More tests => 84;
@@ -1,5 +1,5 @@
# perl
-#$Id: 02_oo_lists_dual_reg_unsorted.t 1304 2008-05-18 23:53:42Z jimk $
+#$Id$
# 02_oo_lists_dual_reg_unsorted.t
use strict;
use Test::More tests => 103;
@@ -1,5 +1,5 @@
# perl
-#$Id: 03_oo_lists_dual_acc_sorted.t 1309 2008-06-01 00:47:38Z jimk $
+#$Id$
# 03_oo_lists_dual_acc_sorted.t
use strict;
use Test::More tests => 86;
@@ -1,5 +1,5 @@
# perl
-#$Id: 04_oo_lists_dual_acc_unsorted.t 1281 2008-05-10 17:09:01Z jimk $
+#$Id$
# 04_oo_lists_dual_acc_unsorted.t
use strict;
use Test::More tests => 109;
@@ -1,5 +1,5 @@
# perl
-#$Id: 05_oo_lists_mult_reg_sorted.t 1317 2008-06-02 23:22:02Z jimk $
+#$Id$
# 05_oo_lists_mult_reg_sorted.t
use strict;
use Test::More tests => 115;
@@ -1,5 +1,5 @@
# perl
-#$Id: 06_oo_lists_mult_reg_unsorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 06_oo_lists_mult_reg_unsorted.t
use strict;
use Test::More tests => 110;
@@ -1,5 +1,5 @@
# perl
-#$Id: 07_oo_lists_mult_acc_sorted.t 1317 2008-06-02 23:22:02Z jimk $
+#$Id$
# 07_oo_lists_mult_acc_sorted.t
use strict;
use Test::More tests => 114;
@@ -1,5 +1,5 @@
# perl
-#$Id: 08_oo_lists_mult_acc_unsorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 08_oo_lists_mult_acc_unsorted.t
use strict;
use Test::More tests => 111;
@@ -1,5 +1,5 @@
# perl
-#$Id: 09_oo_lists_alt_dual_reg_sorted.t 1304 2008-05-18 23:53:42Z jimk $
+#$Id$
# 09_oo_lists_alt_dual_reg_sorted.t
use strict;
use Test::More tests => 79;
@@ -1,5 +1,5 @@
# perl
-#$Id: 10_oo_lists_alt_dual_reg_unsorted.t 1304 2008-05-18 23:53:42Z jimk $
+#$Id$
# 10_oo_lists_alt_dual_reg_unsorted.t
use strict;
use Test::More tests => 103;
@@ -1,5 +1,5 @@
# perl
-#$Id: 11_oo_lists_alt_dual_acc_sorted.t 1308 2008-06-01 00:46:14Z jimk $
+#$Id$
# 11_oo_lists_alt_dual_acc_sorted.t
use strict;
use Test::More tests => 79;
@@ -1,5 +1,5 @@
# perl
-#$Id: 12_oo_lists_alt_dual_acc_unsorted.t 1279 2008-05-10 16:37:42Z jimk $
+#$Id$
# 12_oo_lists_alt_dual_acc_unsorted.t
use strict;
use Test::More tests => 100;
@@ -1,5 +1,5 @@
# perl
-#$Id: 13_oo_lists_alt_mult_reg_sorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# t/13_oo_lists_alt_mult_reg_sorted.t
use strict;
use Test::More tests => 106;
@@ -1,5 +1,5 @@
# perl
-#$Id: 14_oo_lists_alt_mult_reg_unsorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 14_oo_lists_alt_mult_reg_unsorted.t
use strict;
use Test::More tests => 110;
@@ -1,5 +1,5 @@
# perl
-#$Id: 15_oo_lists_alt_mult_acc_sorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# t/15_oo_lists_alt_mult_acc_sorted.t
use strict;
use Test::More tests => 106;
@@ -1,5 +1,5 @@
# perl
-#$Id: 16_oo_lists_alt_mult_acc_unsorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# t/16_oo_lists_alt_mult_acc_unsorted.t
use strict;
use Test::More tests => 110;
@@ -1,5 +1,5 @@
# perl
-#$Id: 17_oo_hashes_dual_reg_sorted.t 1304 2008-05-18 23:53:42Z jimk $
+#$Id$
# 17_oo_hashes_dual_reg_sorted.t
use strict;
use Test::More tests => 76;
@@ -1,5 +1,5 @@
# perl
-#$Id: 18_oo_hashes_dual_reg_unsorted.t 1304 2008-05-18 23:53:42Z jimk $
+#$Id$
# 18_oo_hashes_dual_reg_unsorted.t
use strict;
use Test::More tests => 103;
@@ -1,5 +1,5 @@
# perl
-#$Id: 19_oo_hashes_dual_acc_sorted.t 1282 2008-05-10 17:15:28Z jimk $
+#$Id$
# 19_oo_hashes_dual_acc_sorted.t
use strict;
use Test::More tests => 79;
@@ -1,5 +1,5 @@
# perl
-#$Id: 20_oo_hashes_dual_acc_unsorted.t 1282 2008-05-10 17:15:28Z jimk $
+#$Id$
# 20_oo_hashes_dual_acc_unsorted.t
use strict;
use Test::More tests => 109;
@@ -1,5 +1,5 @@
# perl
-#$Id: 21_oo_hashes_mult_reg_sorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 21_oo_hashes_mult_reg_sorted.t
use strict;
use Test::More tests => 104;
@@ -1,5 +1,5 @@
# perl
-#$Id: 22_oo_hashes_mult_reg_unsorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 22_oo_hashes_mult_reg_unsorted.t
use strict;
use Test::More tests => 110;
@@ -1,5 +1,5 @@
# perl
-#$Id: 23_oo_hashes_mult_acc_sorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 23_oo_hashes_mult_acc_sorted.t
use strict;
use Test::More tests => 104;
@@ -1,5 +1,5 @@
# perl
-#$Id: 24_oo_hashes_mult_acc_unsorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 24_oo_hashes_mult_acc_unsorted.t
use strict;
use Test::More tests => 111;
@@ -1,5 +1,5 @@
# perl
-#$Id: 25_oo_hashes_alt_dual_reg_sorted.t 1309 2008-06-01 00:47:38Z jimk $
+#$Id$
# 25_oo_hashes_alt_dual_reg_sorted.t
use strict;
use Test::More tests => 79;
@@ -1,5 +1,5 @@
# perl
-#$Id: 26_oo_hashes_alt_dual_reg_unsorted.t 1304 2008-05-18 23:53:42Z jimk $
+#$Id$
# 26_oo_hashes_alt_dual_reg_unsorted.t
use strict;
use Test::More tests => 103;
@@ -1,5 +1,5 @@
# perl
-#$Id: 27_oo_hashes_alt_dual_acc_sorted.t 1284 2008-05-11 02:45:50Z jimk $
+#$Id$
# 27_oo_hashes_alt_dual_acc_sorted.t
use strict;
use Test::More tests => 77;
@@ -1,5 +1,5 @@
# perl
-#$Id: 28_oo_hashes_alt_dual_acc_unsorted.t 1284 2008-05-11 02:45:50Z jimk $
+#$Id$
# 28_oo_hashes_alt_dual_acc_unsorted.t
use strict;
use Test::More tests => 100;
@@ -1,5 +1,5 @@
# perl
-#$Id: 29_oo_hashes_alt_mult_reg_sorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 29_oo_hashes_alt_mult_reg_sorted.t
use strict;
use Test::More tests => 104;
@@ -1,5 +1,5 @@
# perl
-#$Id: 30_oo_hashes_alt_mult_reg_unsorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 30_oo_hashes_alt_mult_reg_unsorted.t
use strict;
use Test::More tests => 110;
@@ -1,5 +1,5 @@
# perl
-#$Id: 31_oo_hashes_alt_mult_acc_sorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 31_oo_hashes_alt_mult_acc_sorted.t
use strict;
use Test::More tests => 104;
@@ -1,5 +1,5 @@
# perl
-#$Id: 32_oo_hashes_alt_mult_acc_unsorted.t 1288 2008-05-11 16:51:26Z jimk $
+#$Id$
# 32_oo_hashes_alt_mult_acc_unsorted.t
use strict;
use Test::More tests => 110;
@@ -1,5 +1,5 @@
# perl
-#$Id: 33_func_lists_dual_sorted.t 1318 2008-06-03 00:34:48Z jimk $
+#$Id$
# 33_func_lists_dual_sorted.t
use strict;
use Test::More qw(no_plan); # tests => 50;
@@ -1,5 +1,5 @@
# perl
-#$Id: 34_func_lists_dual_unsorted.t 1322 2008-06-03 02:43:30Z jimk $
+#$Id$
# 34_func_lists_dual_unsorted.t
use strict;
use Test::More tests => 42;
@@ -1,5 +1,5 @@
# perl
-#$Id: 35_func_lists_mult_sorted.t 1317 2008-06-02 23:22:02Z jimk $
+#$Id$
# 35_func_lists_mult_sorted.t
use strict;
use Test::More tests => 51;
@@ -1,5 +1,5 @@
# perl
-#$Id: 36_func_lists_mult_unsorted.t 1300 2008-05-15 23:36:34Z jimk $
+#$Id$
# 36_func_lists_mult_unsorted.t
use strict;
use Test::More tests => 42;
@@ -1,5 +1,5 @@
# perl
-#$Id: 37_func_lists_alt_dual_sorted.t 1320 2008-06-03 00:50:59Z jimk $
+#$Id$
# 37_func_lists_alt_dual_sorted.t
use strict;
use Test::More tests => 50;
@@ -1,5 +1,5 @@
# perl
-#$Id: 38_func_lists_alt_dual_unsorted.t 1299 2008-05-15 23:25:52Z jimk $
+#$Id$
# 38_func_lists_alt_dual_unsorted.t
use strict;
use Test::More tests => 38;
@@ -1,5 +1,5 @@
# perl
-#$Id: 39_func_lists_alt_mult_sorted.t 1299 2008-05-15 23:25:52Z jimk $
+#$Id$
# 39_func_lists_alt_mult_sorted.t
use strict;
use Test::More tests => 43;
@@ -1,5 +1,5 @@
# perl
-#$Id: 40_func_lists_alt_mult_unsorted.t 1299 2008-05-15 23:25:52Z jimk $
+#$Id$
# 40_func_lists_alt_mult_unsorted.t
use strict;
use Test::More tests => 42;
@@ -1,5 +1,5 @@
# perl
-#$Id: 41_func_hashes_dual_sorted.t 1300 2008-05-15 23:36:34Z jimk $
+#$Id$
# 41_func_hashes_dual_sorted.t
use strict;
use Test::More tests => 46;
@@ -1,5 +1,5 @@
# perl
-#$Id: 42_func_hashes_dual_unsorted.t 1300 2008-05-15 23:36:34Z jimk $
+#$Id$
# 42_func_hashes_dual_unsorted.t
use strict;
use Test::More tests => 38;
@@ -1,5 +1,5 @@
# perl
-#$Id: 43_func_hashes_mult_sorted.t 1300 2008-05-15 23:36:34Z jimk $
+#$Id$
# 43_func_hashes_mult_sorted.t
use strict;
use Test::More tests => 43;
@@ -1,5 +1,5 @@
# perl
-#$Id: 44_func_hashes_mult_unsorted.t 1300 2008-05-15 23:36:34Z jimk $
+#$Id$
# 36_func_lists_mult_unsorted.t
use strict;
use Test::More tests => 42;
@@ -1,5 +1,5 @@
# perl
-#$Id: 45_func_hashes_alt_dual_sorted.t 1301 2008-05-15 23:42:36Z jimk $
+#$Id$
# 45_func_hashes_alt_dual_sorted.t
use strict;
use Test::More tests => 46;
@@ -1,5 +1,5 @@
# perl
-#$Id: 46_func_hashes_alt_dual_unsorted.t 1301 2008-05-15 23:42:36Z jimk $
+#$Id$
# 46_func_hashes_alt_dual_unsorted.t
use strict;
use Test::More tests => 38;
@@ -1,5 +1,5 @@
# perl
-#$Id: 47_func_hashes_alt_mult_sorted.t 1301 2008-05-15 23:42:36Z jimk $
+#$Id$
# 47_func_hashes_alt_mult_sorted.t
use strict;
use Test::More tests => 43;
@@ -1,5 +1,5 @@
# perl
-#$Id: 48_func_hashes_alt_mult_unsorted.t 1301 2008-05-15 23:42:36Z jimk $
+#$Id$
# 48_func_hashes_alt_mult_unsorted.t
use strict;
use Test::More tests => 42;
@@ -0,0 +1,193 @@
+# perl
+#$Id$
+# 50_lcf_subset.t
+use strict;
+use Test::More tests => 52;
+use List::Compare;
+
+my @a0 = ( qw| alpha | );
+my @a1 = ( qw| alpha beta | );
+my @a2 = ( qw| alpha beta gamma | );
+my @a3 = ( qw| gamma | );
+
+my ($lc, $LR, $RL);
+
+$lc = List::Compare->new( [], [] );
+$LR = $lc->is_LsubsetR();
+ok($LR, "simple: empty array is subset of itself");
+
+$lc = List::Compare->new( [], [] );
+$RL = $lc->is_RsubsetL();
+ok($RL, "simple: empty array is subset of itself");
+
+$lc = List::Compare->new( \@a0, \@a0 );
+$LR = $lc->is_LsubsetR();
+ok($LR, "simple: array is subset of itself");
+
+$lc = List::Compare->new( \@a0, \@a0 );
+$RL = $lc->is_RsubsetL();
+ok($RL, "simple: array is subset of itself");
+
+$lc = List::Compare->new( \@a0, \@a3 );
+$LR = $lc->is_LsubsetR();
+ok(! $LR, "simple: disjoint are not subsets");
+
+$lc = List::Compare->new( \@a0, \@a3 );
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "simple: disjoint are not subsets");
+
+$lc = List::Compare->new( \@a0, \@a1 );
+$LR = $lc->is_LsubsetR();
+ok($LR, "simple: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "simple: left is subset of right");
+
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "simple: right is not subset of left");
+
+$RL = $lc->is_BsubsetA();
+ok(! $RL, "simple: right is not subset of left");
+
+
+$lc = List::Compare->new( '-u', \@a0, \@a1 );
+$LR = $lc->is_LsubsetR();
+ok($LR, "simple unsorted: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "simple unsorted: left is subset of right");
+
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "simple unsorted: right is not subset of left");
+
+$RL = $lc->is_BsubsetA();
+ok(! $RL, "simple unsorted: right is not subset of left");
+
+
+$lc = List::Compare->new( '--unsorted', \@a0, \@a1 );
+$LR = $lc->is_LsubsetR();
+ok($LR, "simple unsorted long: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "simple unsorted long: left is subset of right");
+
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "simple unsorted long: right is not subset of left");
+
+$RL = $lc->is_BsubsetA();
+ok(! $RL, "simple unsorted long: right is not subset of left");
+
+
+$lc = List::Compare->new( { lists => [ [], [] ] } );
+$LR = $lc->is_LsubsetR();
+ok($LR, "lists: empty array is subset of itself");
+
+$lc = List::Compare->new( { lists => [ [], [] ] } );
+$RL = $lc->is_RsubsetL();
+ok($LR, "lists: empty array is subset of itself");
+
+$lc = List::Compare->new( { lists => [ \@a0, \@a0 ] } );
+$LR = $lc->is_LsubsetR();
+ok($LR, "lists: array is subset of itself");
+
+$lc = List::Compare->new( { lists => [ \@a0, \@a0 ] } );
+$RL = $lc->is_RsubsetL();
+ok($RL, "lists: array is subset of itself");
+
+$lc = List::Compare->new( { lists => [ \@a0, \@a3 ] } );
+$LR = $lc->is_LsubsetR();
+ok(! $LR, "lists: disjoint are not subsets");
+
+$lc = List::Compare->new( { lists => [ \@a0, \@a3 ] } );
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "lists: disjoint are not subsets");
+
+$lc = List::Compare->new( { lists => [ \@a0, \@a1 ] } );
+$LR = $lc->is_LsubsetR();
+ok($LR, "lists: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "lists: left is subset of right");
+
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "lists: right is not subset of left");
+
+$RL = $lc->is_BsubsetA();
+ok(! $RL, "lists: right is not subset of left");
+
+
+$lc = List::Compare->new( { lists => [ \@a0, \@a1 ], unsorted => 1 } );
+$LR = $lc->is_LsubsetR();
+ok($LR, "lists: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "lists: left is subset of right");
+
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "lists: right is not subset of left");
+
+$RL = $lc->is_BsubsetA();
+ok(! $RL, "lists: right is not subset of left");
+
+
+$lc = List::Compare->new( '-a', \@a0, \@a1 );
+$LR = $lc->is_LsubsetR();
+ok($LR, "simple accelerated: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "simple accelerated: left is subset of right");
+
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "simple accelerated: right is not subset of left");
+
+$RL = $lc->is_BsubsetA();
+ok(! $RL, "simple accelerated: right is not subset of left");
+
+
+$lc = List::Compare->new( '--accelerated', \@a0, \@a1 );
+$LR = $lc->is_LsubsetR();
+ok($LR, "simple accelerated long: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "simple accelerated long: left is subset of right");
+
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "simple accelerated long: right is not subset of left");
+
+$RL = $lc->is_BsubsetA();
+ok(! $RL, "simple accelerated long: right is not subset of left");
+
+
+$lc = List::Compare->new( { lists => [ \@a0, \@a1 ], accelerated => 1 } );
+$LR = $lc->is_LsubsetR();
+ok($LR, "lists: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "lists: left is subset of right");
+
+$RL = $lc->is_RsubsetL();
+ok(! $RL, "lists: right is not subset of left");
+
+$RL = $lc->is_BsubsetA();
+ok(! $RL, "lists: right is not subset of left");
+
+
+$lc = List::Compare->new( \@a0, \@a1, \@a2 );
+$LR = $lc->is_LsubsetR();
+ok($LR, "multiple: left is subset of right");
+$LR = $lc->is_LsubsetR(0,1);
+ok($LR, "multiple: left is subset of right");
+$LR = $lc->is_LsubsetR(1,2);
+ok($LR, "multiple: left is subset of right");
+$LR = $lc->is_LsubsetR(0,2);
+ok($LR, "multiple: left is subset of right");
+
+$LR = $lc->is_AsubsetB();
+ok($LR, "multiple: left is subset of right");
+$LR = $lc->is_AsubsetB(0,1);
+ok($LR, "multiple: left is subset of right");
+$LR = $lc->is_AsubsetB(1,2);
+ok($LR, "multiple: left is subset of right");
+$LR = $lc->is_AsubsetB(0,2);
+ok($LR, "multiple: left is subset of right");
+
@@ -0,0 +1,100 @@
+# perl
+#$Id$
+# 50_lcf_subset.t
+use strict;
+use Test::More tests => 28;
+use List::Compare::Functional qw(is_LsubsetR is_RsubsetL);
+
+my @a0 = ( qw| alpha | );
+my @a1 = ( qw| alpha beta | );
+my @a2 = ( qw| alpha beta gamma | );
+my @a3 = ( qw| gamma | );
+
+my ($LR, $RL);
+
+$LR = is_LsubsetR( [ [], [] ] );
+ok($LR, "simple: empty array is subset of itself");
+
+$RL = is_RsubsetL( [ [], [] ] );
+ok($RL, "simple: empty array is subset of itself");
+
+$LR = is_LsubsetR( [ \@a0, \@a0 ] );
+ok($LR, "simple: array is subset of itself");
+
+$RL = is_RsubsetL( [ \@a0, \@a0 ] );
+ok($RL, "simple: array is subset of itself");
+
+$LR = is_LsubsetR( [ \@a0, \@a3 ] );
+ok(! $LR, "simple: disjoint are not subsets");
+
+$RL = is_RsubsetL( [ \@a0, \@a3 ] );
+ok(! $RL, "simple: disjoint are not subsets");
+
+$LR = is_LsubsetR( [ \@a0, \@a1 ] );
+ok($LR, "simple: left is subset of right");
+
+$RL = is_RsubsetL( [ \@a0, \@a1 ] );
+ok(! $RL, "simple: right is not subset of left");
+
+$LR = is_LsubsetR( [ \@a1, \@a0 ] );
+ok(! $LR, "simple: left is not subset of right");
+
+$RL = is_RsubsetL( [ \@a1, \@a0 ] );
+ok($RL, "right is subset of left");
+
+$LR = is_LsubsetR( { lists => [ [], [] ] } );
+ok($LR, "hashref lists: empty array is subset of itself");
+
+$RL = is_RsubsetL( { lists => [ [], [] ] } );
+ok($LR, "hashref lists: empty array is subset of itself");
+
+$LR = is_LsubsetR( { lists => [ \@a0, \@a0 ] } );
+ok($LR, "hashref lists: array is subset of itself");
+
+$RL = is_RsubsetL( { lists => [ \@a0, \@a0 ] } );
+ok($RL, "hashref lists: array is subset of itself");
+
+$LR = is_LsubsetR( { lists => [ \@a0, \@a3 ] } );
+ok(! $LR, "hashref lists: disjoint are not subsets");
+
+$RL = is_RsubsetL( { lists => [ \@a0, \@a3 ] } );
+ok(! $RL, "hashref lists: disjoint are not subsets");
+
+$LR = is_LsubsetR( { lists => [ \@a0, \@a1 ] } );
+ok($LR, "hashref lists: left is subset of right");
+
+$RL = is_RsubsetL( { lists => [ \@a0, \@a1 ] } );
+ok(! $RL, "hashref lists: right is not subset of left");
+
+$LR = is_LsubsetR( { lists => [ \@a1, \@a0 ] } );
+ok(! $LR, "hashref lists: left is not subset of right");
+
+$RL = is_RsubsetL( { lists => [ \@a1, \@a0 ] } );
+ok($RL, "right is subset of left");
+
+
+$LR = is_LsubsetR( [ \@a0, \@a1 ], [ 0,1 ] );
+ok($LR, "2 indices arrayref: left is subset of right");
+
+$LR = is_LsubsetR( [ \@a1, \@a0 ], [ 0,1 ] );
+ok(! $LR, "2 indices arrayref: left is not subset of right");
+
+$LR = is_LsubsetR( [ \@a0, \@a1, \@a2 ], [ 1,2 ] );
+ok($LR, "3 indices arrayref: left is subset of right");
+
+$LR = is_LsubsetR( [ \@a2, \@a1, \@a0 ], [ 1,2 ] );
+ok(! $LR, "3 indices arrayref: left is not subset of right");
+
+
+$LR = is_LsubsetR( { lists => [ \@a0, \@a1 ], pair => [ 0,1 ] } );
+ok($LR, "lists pair 2 indices: left is subset of right");
+
+$LR = is_LsubsetR( { lists => [ \@a1, \@a0 ], pair => [ 0,1 ] } );
+ok(! $LR, "lists pair 2 indices: left is not subset of right");
+
+$LR = is_LsubsetR( { lists => [ \@a0, \@a1, \@a2 ], pair => [ 1,2 ] } );
+ok($LR, "lists pair 3 indices: left is subset of right");
+
+$LR = is_LsubsetR( { lists => [ \@a2, \@a1, \@a0 ], pair => [ 1,2 ] } );
+ok(! $LR, "lists pair 3 indices: left is not subset of right");
+
@@ -1,5 +1,5 @@
# perl
-#$Id: 90_oo_errors.t 1326 2008-06-04 03:42:40Z jimk $
+#$Id$
# 01_oo_lists_dual_reg_sorted.t
use strict;
use Test::More tests => 30;
@@ -1,5 +1,5 @@
# perl
-#$Id: 91_func_errors.t 1308 2008-06-01 00:46:14Z jimk $
+#$Id$
# 91_func_errors.t
use strict;
use Test::More tests => 176;