2

To compare each element of arrays that I know are the same length (and which have a predictable order) in perl we have each_arrayref which can be added to useful subroutines or just used directly:

use List::AllUtils qw/each_arrayref/;

my ($arr1, $arr2) = ( [10, 31, 12], [20, 21, 14] );

my $iterate_elems = each_arrayref($arr1, $arr2); 
while ( my ($x, $y) = $iterate_elems->() ) { 
   say $x lt $y ? "$x is lower " : "$x is higher" ; 
}

or one-lineishly for cut and paste:

perl -MList::AllUtils=each_arrayref -E '
  my $iter = each_arrayref([10, 31, 12], [20, 21, 14]); 
  while ( my ($x, $y) = $iter->() ){ 
  say $x lt $y ? "$x lower" : "$x higher"}'

But this seems a tad awkward and not completely foolproof. I try to use a descriptive term like $iterate_elems as the iterating function reference to help. Perhaps I don't use this enough for it to seem obvious.

In perl6 there are metaoperators which allow for all kinds of fairly succinct and cool list comparisons and munging. This leads me to think there must be a way one could use operator overloading in perl5 to do this. Can anyone comment on the wisdom of this? It seems like it might be easier to understand code written in a way that applies operators to a series of lists instead of iterating through the lists to apply operators. Perhaps creative use of map or List::MoreUtils's apply would achieve the same thing.

Astonishing perl6 code samples especially welcome.

6
  • Maybe I'm missing the point of your question, but... If you know the length is the same, what's wrong with for my $i (0 .. $#array1) { say $array1[$i], $array2[$i]; } ? Commented Jan 22, 2015 at 22:40
  • Normally the array or list would be much larger and one might want to do more more comparisons of the elements which is what I think each_arrayref is supposed to make possible. But yes simpler is better when possible. Commented Jan 22, 2015 at 22:48
  • I guess I'm still not getting it. How would an array with more elements, or needing to make more comparisons, change the logic in the loop? Perhaps a more concrete example is in order... Commented Jan 22, 2015 at 22:57
  • 2
    $ perl6 -e 'say (10, 31, 12) Zcmp (20, 21, 4 )' results in Less More More Commented Jan 23, 2015 at 1:50
  • @ThisSuitIsBlackNot point well taken - my example is too simple. My understanding of each_arrayref (and some other functions in List::MoreUtils and friends) is that they provide a way of packaging more straightforward constructs like loops so they can be "extended" in different ways: e.g. nested foreach loops for comparing array elements are clear and familiar, but for three or more arrays, or an array of keys from a hash of arrayrefs etc. an $iterator->() coderef can save on parens. ;-) Commented Jan 23, 2015 at 4:06

1 Answer 1

1

Since you're using List::AllUtils, how about pairwise?

use List::AllUtils qw(pairwise);

my @arr1 = (10, 31, 12);
my @arr2 = (20, 21, 14);

pairwise { 
    print $a lt $b ? "$a is lower\n" : "$a is higher\n"
} @arr1, @arr2;

That fits your problem as stated, and seems simpler to me, but 'simple' is slippery... Best of luck!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.