Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Unusual sorting requirement

by thezip (Vicar)
on Sep 12, 2018 at 21:13 UTC ( #1222256=perlquestion: print w/replies, xml ) Need Help??
thezip has asked for the wisdom of the Perl Monks concerning the following question:

G'day monks!

I have two arrays of array refs. Each of these has a "date" column, but the columnar position is not the same for both arrays.

There is another field that identifies which array is currently being looked at, and hence can indicate the position of the date column.

What sorting strategy can I use to interleave the two arrays, sorting by the applicable date ?

#! perl use strict; use warnings; use JSON; my $json = JSON->new(); my $ary1 = [ [ 1,1,1,1,1,'2018-03-01', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-02-15', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-04-11', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-03-11', 'src1', 1,1,1,1 ], ]; my $ary2 = [ [ 2,2,2,2,'2018-03-02', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-01-25', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-04-22', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-03-22', 2, 'src2', 2,2,2,2 ], ]; sub by_dates { # What should this sort routine look like so # that both arrays are interleaved, sorting # by the applicable date column? } my @combined = (@$ary1, @$ary2); my @sorted = sort by_dates @combined; print $json->encode(\@sorted);

*My* tenacity goes to eleven...

Replies are listed 'Best First'.
Re: Unusual sorting requirement
by tybalt89 (Vicar) on Sep 12, 2018 at 23:16 UTC
    #!/usr/bin/perl # https://perlmonks.org/?node_id=1222256 use strict; use warnings; my $ary1 = [ [ 1,1,1,1,1,'2018-03-01', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-02-15', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-04-11', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-03-11', 'src1', 1,1,1,1 ], ]; my $ary2 = [ [ 2,2,2,2,'2018-03-02', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-01-25', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-04-22', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-03-22', 2, 'src2', 2,2,2,2 ], ]; my @sorted = map $_->[0], sort { $a->[1] cmp $b->[1] } map( [ $_, $_->[5] ], @$ary1 ), map( [ $_, $_->[4] ], @$ary2 ); use Data::Dump 'dd'; dd \@sorted;

    Outputs

    [ [2, 2, 2, 2, "2018-01-25", 2, "src2", 2, 2, 2, 2], [1, 1, 1, 1, 1, "2018-02-15", "src1", 1, 1, 1, 1], [1, 1, 1, 1, 1, "2018-03-01", "src1", 1, 1, 1, 1], [2, 2, 2, 2, "2018-03-02", 2, "src2", 2, 2, 2, 2], [1, 1, 1, 1, 1, "2018-03-11", "src1", 1, 1, 1, 1], [2, 2, 2, 2, "2018-03-22", 2, "src2", 2, 2, 2, 2], [1, 1, 1, 1, 1, "2018-04-11", "src1", 1, 1, 1, 1], [2, 2, 2, 2, "2018-04-22", 2, "src2", 2, 2, 2, 2], ]

      Here's a better optimization:

      printf "[%s]", join ",", map substr($_, 10), sort map($_->[5].$json->encode($_), @$ary1), map($_->[4].$json->encode($_), @$ary2);

      Thank you for the ST!


      *My* tenacity goes to eleven...
Re: Unusual sorting requirement
by haukex (Canon) on Sep 12, 2018 at 21:25 UTC
    There is another field that identifies which array is currently being looked at, and hence can indicate the position of the date column.

    Which column is that? I'm going to take a guess it's src1/src2. Also, I'm assuming string comparisons for the dates are ok, which should hold true if all the dates are formatted as you showed. I hope this is what you're looking for?

    <update> I should have mentioned right off the bat that this is not the most efficient solution, and a Schwartzian transform, like LanX said and tybalt89 showed, helps in that regard. </update>

    use warnings; use strict; use Data::Dump; my $ary1 = [ [ 1,1,1,1,1,'2018-03-01', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-02-15', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-04-11', 'src1', 1,1,1,1 ], [ 1,1,1,1,1,'2018-03-11', 'src1', 1,1,1,1 ], ]; my $ary2 = [ [ 2,2,2,2,'2018-03-02', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-01-25', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-04-22', 2, 'src2', 2,2,2,2 ], [ 2,2,2,2,'2018-03-22', 2, 'src2', 2,2,2,2 ], ]; my @sorted = sort { $$a[$$a[6] eq 'src1' ?5:4] cmp $$b[$$b[6] eq 'src1' ?5:4] } (@$ary1, @$ary2); dd @sorted; __END__ ( [2, 2, 2, 2, "2018-01-25", 2, "src2", 2, 2, 2, 2], [1, 1, 1, 1, 1, "2018-02-15", "src1", 1, 1, 1, 1], [1, 1, 1, 1, 1, "2018-03-01", "src1", 1, 1, 1, 1], [2, 2, 2, 2, "2018-03-02", 2, "src2", 2, 2, 2, 2], [1, 1, 1, 1, 1, "2018-03-11", "src1", 1, 1, 1, 1], [2, 2, 2, 2, "2018-03-22", 2, "src2", 2, 2, 2, 2], [1, 1, 1, 1, 1, "2018-04-11", "src1", 1, 1, 1, 1], [2, 2, 2, 2, "2018-04-22", 2, "src2", 2, 2, 2, 2], )

      That works for me -- thx!


      *My* tenacity goes to eleven...
Re: Unusual sorting requirement
by ikegami (Pope) on Sep 12, 2018 at 22:48 UTC

    Have you considered normalizing your data so you don't have to deal with rows of two different formats both here and again down the line?

Re: Unusual sorting requirement
by LanX (Archbishop) on Sep 12, 2018 at 21:54 UTC
    > What sorting strategy can I use to interleave the two arrays, sorting by the applicable date ?

    I'd rather solve it with a Schwartzian transform instead of cramming the whole logic into one sort term.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    update

    like shown by tybalt in the meantime

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2018-11-16 09:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My code is most likely broken because:
















    Results (193 votes). Check out past polls.

    Notices?
    • (Sep 10, 2018 at 22:53 UTC) Welcome new users!