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

Dear Masters,
I have a simple array which I want to print the adjacent element together. But my script below doesn't seem to do the job:
# Number of elements in the array are always EVEN my @arr = qw (J K L M N O); my %done; OUT: foreach my $elem(@arr) { IN: foreach my $elem2(@arr) { next IN if ($elem eq $elem2); next IN if ($done{$elem2." - ". $elem}); print "$elem - $elem2\n"; $done{$elem." - ".$elem2} = 1; } }
It somehow doesn't print the desired result like this:
J - K L - M N - O
What's wrong with my script above?

---
neversaint and everlastingly indebted.......

Replies are listed 'Best First'.
Re: Adjacent Looping
by moritz (Cardinal) on Aug 22, 2007 at 07:16 UTC
    For adjacent entries you don't have to iterate over the array twice:

    use warnings; use strict; my @a = qw(J K L M N O); my %done; for (my $i = 0; $i < @a; $i += 2){ my $str = $a[$i] . ' ' . $a[$i+1]; print $str, "\n"; $done{$str} = 1; }

    In this case %done isn't really used, if you want each pair to be printed only once you can check if $done{$str} is already set.

Re: Adjacent Looping
by GrandFather (Saint) on Aug 22, 2007 at 07:36 UTC

    If you don't mind clobbering the array you could just:

    use warnings; use strict; my @arr = qw (J K L M N O); print join (' - ', splice @arr, 0, 2), "\n" while @arr;

    Prints:

    J - K L - M N - O

    or if you need the unique check:

    use warnings; use strict; my @arr = qw (J K L M N O J K); my %done; while (@arr) { my $str = join ' - ', splice @arr, 0, 2; next if exists $done{$str}; $done{$str}++; print "$str\n"; }

    DWIM is Perl's answer to Gödel
Re: Adjacent Looping
by hangon (Deacon) on Aug 22, 2007 at 07:33 UTC

    Too many loops. Try this:

    my @arr = qw (J K L M N O); my $i = 0; while($i < scalar @arr){ print "$arr[$i] - $arr[$i+1]\n"; $i += 2; }
Re: Adjacent Looping
by ikegami (Patriarch) on Aug 22, 2007 at 14:04 UTC
    A more funcional approach:
    use List::MoreUtils qw( pairwise ); my @arr = qw( J K L M N O ); my %done; my @pairs = grep !$done{$_}++, # Remove duplicates pairwise { "$a - $b" } @arr; print map "$_\n", @pairs;

    The above is basically the same as:

    my @arr = qw( J K L M N O ); my %done; my @pairs; while (@arr) { my $pair = join(' - ', splice(@arr, 0, 2)); next if $done{$pair}++; push @pairs, $pair; } print "$_\n" for @pairs;
Re: Adjacent Looping
by wfsp (Abbot) on Aug 22, 2007 at 13:27 UTC
    In your example the input is sorted. A hash could help:
    my %hash = qw (J K L M N O); print qq{$_ => $hash{$_}\n} for sort keys %hash;