biologistatsea has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I'm writing a script for performing comparisons among files - but the total number of file inputs varies from case to case.

I would like to use the List::Compare methods for performing these comparisons. However I don't know how to pass an unknown number of array references to build the List::compare object.

For example, after reading the inputs my data might be stored in %HASH : $HASH{$filename}{$groupname}=group members. I can then loop through the hash and put the groupnames for each file in an array. But how do I collect these arrays and pass references to them to List::Compare?

Here's an example of some minimal code of the sort of thing I've tried to get the array references into the object. Any help or solutions would be very much appreciated!

use warnings; use strict; use List::Compare; my @S1 = ( 'G1', 'G3', 'G5' ); my @S2 = ( 'G1', 'G3', 'G5', 'G7', 'G12' ); my @S3 = ( 'G1', 'G5' ); my @A = ('\@S1', '\@S2', '\@S3'); my $var = join ',' , @A; my $lc = List::Compare->new('--unsorted', "$var"); my @intersection = $lc->get_intersection; print "intesection is @intersection\n";

Replies are listed 'Best First'.
Re: Building List::Compare objects for unknown numbers of objects
by hippo (Archbishop) on Nov 21, 2018 at 11:38 UTC

    As the documentation shows, you need to pass listrefs, not a string.

    use strict; use warnings; use List::Compare; my @S1 = ( 'G1', 'G3', 'G5' ); my @S2 = ( 'G1', 'G3', 'G5', 'G7', 'G12' ); my @S3 = ( 'G1', 'G5' ); my @A = (\@S1, \@S2, \@S3); my $lc = List::Compare->new('--unsorted', @A); my @intersection = $lc->get_intersection; print "intesection is @intersection\n";
      Great - thanks for your help. I read the documentation quite carefully and was aware that you need to pass array references. But to someone of my background (biologist with a little self-taught Perl) it wasn't obvious to me that the '->new' method would interpret the @A to provide the array references to generate the object. I suppose I thought it would need something to tell it to look at the contents of @A instead of @A itself. Instead I thought that perl would interpolate the "$var1" first and then the resulting text would be correctly interpreted by the method. I obviously lack some basic understanding here...
        I suppose I thought it would need something to tell it to look at the contents of @A instead of @A itself.

        Quite the reverse. You have to work at it in order to refer to the array rather than its contents. Consider these two separate lines from the code above:

        print "intesection is @intersection\n";

        Here, despite being contained within a string, it is the contents of the array which are printed, not the array as a container.

        my @A = (\@S1, \@S2, \@S3);

        Whereas here, we have had to create references to each of the S arrays so that they are not flattened when assigning to @A.

        Further reading: Arrays: A Tutorial/Reference, perldata, perlref