James E Keenan > List-Compare-0.38 > List::Compare

Download:
List-Compare-0.38.tar.gz

Dependencies

Annotate this POD

Related Modules

Data::Dumper
List::Util
Array::Compare
File::Find
Test::More
Algorithm::Diff
String::Approx
Set::Scalar
DBD::CSV
Tie::File
more...
By perlmonks.org

CPAN RT

Open  0
View/Report Bugs
Module Version: 0.38   Source   Latest Release: List-Compare-0.39

NAME ^

List::Compare - Compare elements of two or more lists

VERSION ^

This document refers to version 0.38 of List::Compare. This version was released September 05, 2013.

SYNOPSIS ^

The bare essentials:

    @Llist = qw(abel abel baker camera delta edward fargo golfer);
    @Rlist = qw(baker camera delta delta edward fargo golfer hilton);

    $lc = List::Compare->new(\@Llist, \@Rlist);

    @intersection = $lc->get_intersection;
    @union = $lc->get_union;

... and so forth.

DISCUSSION: Modes and Methods ^

Regular Case: Compare Two Lists

Accelerated Case: When User Only Wants a Single Comparison

Multiple Case: Compare Three or More Lists

Multiple Accelerated Case: Compare Three or More Lists but Request Only a Single Comparison among the Lists

Passing Seen-hashes to the Constructor Instead of Arrays

DISCUSSION: Principles ^

General Comments

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. 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 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 lists.

Except for List::Compare's get_bag() method, 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 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: Did I see this item in this list at all? Only when you use 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?

List::Compare Modes

In its current implementation List::Compare has four modes of operation.

Miscellaneous Methods

It would not really be appropriate to call get_shared() and 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 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 get_Aonly(), get_Bonly() and get_AorBonly() as aliases for get_unique(), get_complement() and 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.

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: List::Compare::SeenHash. The code for that looked like this:

    use List::Compare::SeenHash;

    my %Llist = (
       abel     => 2,
       baker    => 1,
       camera   => 1,
       delta    => 1,
       edward   => 1,
       fargo    => 1,
       golfer   => 1,
    );

    my %Rlist = (
       baker    => 1,
       camera   => 1,
       delta    => 2,
       edward   => 1,
       fargo    => 1,
       golfer   => 1,
       hilton   => 1,
    );

    my $lcsh = List::Compare::SeenHash->new(\%Llist, \%Rlist);

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 either a series of array references 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 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 Unix text editor vi:

    :1,$s/List::Compare::SeenHash/List::Compare/gc

A Non-Object-Oriented Interface: List::Compare::Functional

Version 0.21 of List::Compare introduced List::Compare::Functional, a functional (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 '-a' flag in the function call. List::Compare::Functional will return unsorted comparisons of two lists by passing '-u' or '--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.

ASSUMPTIONS AND QUALIFICATIONS ^

The program was created with Perl 5.6. The use of h2xs to prepare the module's template installed 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 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.

HISTORY, REFERENCES AND DEVELOPMENT ^

The Code Itself

List::Compare is based on code presented by Tom Christiansen & Nathan Torkington in Perl Cookbook http://www.oreilly.com/catalog/cookbook/ (a.k.a. the 'Ram' book), O'Reilly & Associates, 1998, Recipes 4.7 and 4.8. Similar code is presented in the Camel book: Programming Perl, by Larry Wall, Tom Christiansen, Jon Orwant. 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 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 Object Oriented Perl 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 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.

The Inspiration

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 http://perl.plover.com/ to the New York Perlmongers http://ny.pm.org/. See http://www.perl.com/pub/a/2000/11/repair3.html.

The first public presentation of this module took place at Perl Seminar New York 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.

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.

In a November 2003 Perl Seminar New York presentation, Ben Holtzman discussed the performance costs entailed in Perl's 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 The Perl Journal (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, 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 (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, get_unique_all and 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.

If You Like List::Compare, You'll Love ...

While preparing this module for distribution via CPAN, I had occasion to 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. (Warning: The following discussion is only valid as of June 2002. Some of these modules may have changed since then.)

BUGS ^

There are no bug reports outstanding on List::Compare as of the most recent CPAN upload date of this distribution.

SUPPORT ^

Please report any bugs by mail to bug-List-Compare@rt.cpan.org or through the web interface at http://rt.cpan.org.

AUTHOR ^

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: September 05, 2013.

COPYRIGHT ^

Copyright (c) 2002-13 James E. Keenan. United States. All rights reserved. This is free software and may be distributed under the same terms as Perl itself.

DISCLAIMER OF WARRANTY ^

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE ''AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 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.

syntax highlighting: