perl - Sorting multidimensional array with exceptions -
i have file contains time , data. need sort array time, there 2 snags: if time 23:59:59:999 or null, needs stay in relation else. i've taken in file , placed in array of arrays.
for example:
data1 10:25:34.001 data2 data1 10:25:34.002 data2 data1 10:25:34.005 data2 data1 null data2 data1 null data2 data1 null data2 data1 10:25:34.006 data2 data1 10:25:34.007 data2 data1 10:25:34.008 data2 data1 23:59:59:999 data2 data1 23:59:59:999 data2 data1 10:25:34.003 data2 data1 10:25:34.004 data2 data1 10:25:34.010 data2 data1 10:25:34.011 data2
should become:
data1 10:25:34.001 data2 data1 10:25:34.002 data2 data1 10:25:34.003 data2 data1 10:25:34.004 data2 data1 10:25:34.005 data2 data1 null data2 data1 null data2 data1 null data2 data1 10:25:34.006 data2 data1 10:25:34.007 data2 data1 10:25:34.008 data2 data1 23:59:59:999 data2 data1 23:59:59:999 data2 data1 10:25:34.010 data2 data1 10:25:34.011 data2
what have done sort them separate "blocks" (time, null times etc) when dump array of data looks like:
( [ [ "data1", "10:25:34.001", "data2", ], [ "data1", "10:25:34.002", "data2", ], [ "data1", "10:25:34.005", "data2", ], ], [ [ "data1", "null", "data2", ], [ "data1", "null", "data2", ], [ "data1", "null", "data2", ], ], [ [ "data1", "10:25:34.006", "data2", ], [ "data1", "10:25:34.007", "data2", ], [ "data1", "10:25:34.008", "data2", ], ], [ [ "data1", "23:59:59:999", "data2", ], [ "data1", "23:59:59:999", "data2", ], ], [ [ "data1", "10:25:34.003", "data2", ], [ "data1", "10:25:34.004", "data2", ], [ "data1", "10:25:34.010", "data2", ], [ "data1", "10:25:34.011", "data2", ], ] )
my idea find maximum value "first" block , ignore "null" , "23:59:59.999" blocks, , push values in remaining block larger maximum value of "first" block.
i'm having difficulty moving times between separate blocks , sort it, , wondering if had advise on how (or if there better way of sorting structure i've got far) ?
to achieve want, cannot sort original data structure. need transform rows relative positions want preserve attached preceding elements.
here's updated version bit better first implementation posted (see edit history if curious):
#!/usr/bin/env perl use strict; use warnings; @data = [ [ split ' ', scalar <data> ] ]; while (my $row = <data>) { next unless $row =~ /\s/; @x = split ' ', $row; if (($x[1] eq 'null') or ($x[1] eq '23:59:59:999')) { push @{ $data[-1] }, \@x; next; } push @data, [ \@x ]; } @data = map @$_, sort { $a->[0][1] cmp $b->[0][1] } @data; print "@$_\n" @data; __data__ data1 10:25:34.001 data2 data1 10:25:34.002 data2 data1 10:25:34.005 data2 data1 null data2 data1 null data2 data1 null data2 data1 10:25:34.006 data2 data1 10:25:34.007 data2 data1 10:25:34.008 data2 data1 23:59:59:999 data2 data1 23:59:59:999 data2 data1 10:25:34.003 data2 data1 10:25:34.004 data2 data1 10:25:34.010 data2 data1 10:25:34.011 data2
output:
data1 10:25:34.001 data2 data1 10:25:34.002 data2 data1 10:25:34.003 data2 data1 10:25:34.004 data2 data1 10:25:34.005 data2 data1 null data2 data1 null data2 data1 null data2 data1 10:25:34.006 data2 data1 10:25:34.007 data2 data1 10:25:34.008 data2 data1 23:59:59:999 data2 data1 23:59:59:999 data2 data1 10:25:34.010 data2 data1 10:25:34.011 data2
this assume first line of data not null
or midnight event. can use sentry element if first row of data may contain null
or midnight event:
#!/usr/bin/env perl use strict; use warnings; @data = [ [ undef, undef, undef ] ]; while (my $row = <data>) { next unless $row =~ /\s/; @x = split ' ', $row; if (($x[1] eq 'null') or ($x[1] eq '23:59:59:999')) { push @{ $data[-1] }, \@x; next; } push @data, [ \@x ]; } @data = map @$_, sort { $a->[0][1] or return -1; $b->[0][1] or return 1; $a->[0][1] cmp $b->[0][1] } @data; shift @data; print "@$_\n" @data;
we make sure sentry element sorts before other element, , remove before doing further data.
Comments
Post a Comment