Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Comparing and Aligning arrays

by abd (Initiate)
on Apr 03, 2014 at 23:59 UTC ( #1081043=perlquestion: print w/ replies, xml ) Need Help??
abd has asked for the wisdom of the Perl Monks concerning the following question:

Hi

How can I compare three lists in order to aling their values. For example, if I have the following lists:

List1 List2 List3

a a b

b b c

c d d

How can I get the following output:

List1 List2 List3

a a -

b b b

c - c

- d d

It's very important for me to keep the original order.

Thanks.

Comment on Comparing and Aligning arrays
Re: Comparing and Aligning arrays
by LanX (Canon) on Apr 04, 2014 at 00:04 UTC

    What did you try? Can you show us code?

    Hint: Could be done with a hash of arrays.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re: Comparing and Aligning arrays
by ww (Bishop) on Apr 04, 2014 at 00:40 UTC

    I can see (I think) how you transform

    a a b
    to
    a a -
    and
    a a b b b c

    to
    b b b
    and
    b b c c d d

    to - d d
    but the rule I intuit for those doesn't work for the transformation of
    b b c c d d

    to
    c - c

    CODE TAGS...

    <c> ... data here
    (even multiline data)... </c>
    might help us to understand how you get from the source of the list to the output; that is, by what rule(s) are you doing the tranformations?

    or is it just too late in the evening for me to understand?


    Questions containing the words "doesn't work" (or their moral equivalent) will usually get a downvote from me unless accompanied by:
    1. code
    2. verbatim error and/or warning messages
    3. a coherent explanation of what "doesn't work actually means.
Re: Comparing and Aligning arrays
by AnomalousMonk (Monsignor) on Apr 04, 2014 at 02:15 UTC

    I, also, don't understand the rule for positioning the  '-' (hyphen) filler character(s), but here's an approach. (Update: I guess I should also admit I don't really understand 'alignment' either as used in the context of the OP.) Maybe not the most efficient, but I'm hopelessly addicted to regexen.

    c:\@Work\Perl\monks>perl -wMstrict -le "use List::Util qw(max); use Data::Dump; ;; my @List1 = qw(a a b); my @List2 = qw(b b c); my @List3 = qw(c d d); ;; my @runs = do { my $cat = join '', @List1, @List2, @List3; my $s; grep $s = !$s, $cat =~ m{ ((.) \2*) }xmsg; }; ;; my $longest = -1 + max map length, @runs; my @padding = ('-') x $longest; ;; my @padded = map [ (split(''), @padding)[0 .. $longest] ], @runs; dd \@padded; " [ ["a", "a", "-"], ["b", "b", "b"], ["c", "c", "-"], ["d", "d", "-"], ]

    Update: Here's another, slightly different approach using unpack; might be slightly faster.

    c:\@Work\Perl\monks>perl -wMstrict -le "use List::Util qw(max); use Data::Dump; ;; my @List1 = qw(a a b); my @List2 = qw(b b c); my @List3 = qw(c d d); ;; my @runs = do { my $cat = join '', @List1, @List2, @List3; my $s; grep $s = !$s, $cat =~ m{ ((.) \2*) }xmsg; }; ;; my $max_pad = -1 + max map length, @runs; my $padding = '-' x $max_pad; ;; my @padded = map [ unpack qq{a (a)$max_pad}, $_ . $padding ], @runs; dd \@padded; " [ ["a", "a", "-"], ["b", "b", "b"], ["c", "c", "-"], ["d", "d", "-"], ]
Re: Comparing and Aligning arrays
by abd (Initiate) on Apr 04, 2014 at 02:26 UTC

    Dear All,

    Thank you for the replays

    What I'm aiming for is to have new aligned lists where in raw number i for all of them I should have even the same charecter or "-". When I'll but "-" all the following items in the list should be shifted down

    it's very important for me to keep the original order.

    Thanks again

      What I'm aiming for is to have new aligned lists where in raw number i for all of them I should have even the same charecter or "-". When I'll but "-" all the following items in the list should be shifted down

      I'm very sorry, but I don't understand this at all. In addition to a clarifying verbal description, could you perhaps give us another example? (Within  <c> ... </c> code tags of course; please see Markup in the Monastery.) For instance, what separator distribution would you expect from the following (assuming it's a valid set of lists):

      my @List1 = qw(a a b); my @List2 = qw(b b c); my @List3 = qw(d d e);
Re: Comparing and Aligning arrays (Diff)
by tye (Cardinal) on Apr 04, 2014 at 06:09 UTC

    Sounds like you might want an algorithm like the one provided in Algorithm::Diff.

    - tye        

      Dear Tye

      Thanks for mentioning the module Algorithm::Diff. I was looking for such module, this could help me.

      Cheers

      Abd

Re: Comparing and Aligning arrays
by kcott (Abbot) on Apr 04, 2014 at 07:25 UTC

    G'day abd,

    Welcome to the monastery.

    As others have pointed out, your requirements are unclear and, as you've shown all data as paragraph text, the output format cannot be determined.

    Also note that "It's very important for me to keep the original order." does not seem to match your required output: 1st input row is a a b and 1st output row is a a - (only the first two characters are in the same order); 1st input column is a b c and 1st output column is a b c - (only the first three characters are in the same order). You need to clarify what "original order" you are referring to.

    Assuming both instances of "List1 List2 List3" are part of the description, i.e. not part of input or output data, then the following code transforms your provided input to your wanted output.

    #!/usr/bin/env perl use strict; use warnings; my %list = (1 => [qw{a b c}], 2 => [qw{a b d}], 3 => [qw{b c d}]); my (%align, %seen); %{$align{$_}} = map { ++$seen{$_}; $_ => undef } @{$list{$_}} for keys + %list; for my $char (sort keys %seen) { for my $list (sort keys %align) { print exists $align{$list}{$char} ? $char : '-', ' '; } print "\n"; }

    Output:

    a a - b b b c - c - d d

    [Please read the guidelines in "How do I post a question effectively?" and follow them in any future postings.]

    -- Ken

      Dear Ken & All

      Please accept my apology for the weak explanation of what I need. This is my first question on perlmonks. I'll try to follow the instractions you sent for my next question.

      The code you drafted can solve my problem, I highly appreciate you efforts.

      Cheers

      Abd

      Oooooh... So you're saying that  List1 List2 List3 are actually headers and the list items descend below each header. So the data should really look something like
      List1 List2 List3
        a     a     b
        b     b     c
        c     d     d
      translating (to pseudocode) as
      List1 = [qw{a b c}];  List2 = [qw{a b d}];  List3 = [qw{b c d}];

      That's a much better guess than mine, and from the tone of abd's reply may even be right. When I first saw your post, I thought you'd lost your mind, but I've switched to ++.

        "Oooooh... So you're saying that List1 List2 List3 are actually headers ..."

        At first, I did read the rows as being the lists and struggled to work out how the transformation was supposed to be accomplished.

        I don't recall the exact thought process: I think three "ListN" in both input and input matching three columns in both (but not four rows in the output) probably led to the guess I made.

        "When I first saw your post, I thought you'd lost your mind, but I've switched to ++."

        Thanks for generating a hearty chuckle at my end: a good start to my day. :-)

        -- Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1081043]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (18)
As of 2014-08-22 19:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (163 votes), past polls