Perl two-dimensional array sorting based on single element value with exceptions

I am currently working with a two-dimensional array with information about goals scored. Each element in the first array is an array with different information about the target. The second element in this array is the minute (1-90), because I want them to be in sequential order so that I can determine what they did. I use the value of "minutes" to sort with this:

@allinfogoals = sort { $a->[1] <=> $b->[1] } @allinfogoals; 

This works great until I came across goals that were scored in extra time. The protocol for them is displayed as "90 + 2" or "45 + 3". Now I can just add them together, but this can lead to the wrong order. In this case, a goal scored before half a century can be saved as a goal AFTER a goal that was counted shortly after the start of the second half.

So, I find the minutes that have this 90 + x format and split them into "+". I save the first value, where I regularly store minutes in the array, but I added another one at the end of the array (12th element), and I put this second part (minutes in extra time). That is 0 when it is a normal target.

How can I change the sorting above to compensate for this and does it maintain the correct order?

+4
source share
3 answers

It looks like you want to sort by one key first, and if this key is the same, then you want to sort the second key.

eg. you want 45 + 2 to be sorted between 45 and 46.

You can do this simply by using:

 @ls = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @ls 

Only if the first key is the same, consult the second key.

Here is a complete example:

 my @allinfogoals=( [ 46, 0 ], [ 45, 2 ], [ 45, 0 ], [ 33, 0 ], [ 91, 0 ], [ 90, 2 ], ); @allinfogoals=sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @allinfogoals; use Data::Dump; dd \@allinfogoals; 

And the result:

 [[33, 0], [45, 0], [45, 2], [46, 0], [90, 2], [91, 0]] 
+5
source

Here is a brute force solution in which there is not much refinement in it, but it does the job. It does not work with a two-dimensional data structure, if not adapted, but on the other hand, I do not know what your data structure looks like.

 use strict; use warnings; use feature 'say'; my @data = qw(22 45+3 45 46 90 90+3); my @sorted = map $_->[2], # turn back to org string sort { $a->[0] <=> $b->[0] || # default sort by period number $a->[1] <=> $b->[1] # or by minute } map mysort($_), @data; # map all minutes to 3-element array say for @sorted; sub mysort { my $time = shift; if ($time =~ /45\+(\d+)/) { return [1, 45+$1, $time]; } elsif ($time =~ /90\+(\d+)/) { return [2, 90+$1, $time]; } else { my $period = ($time <= 45 ? 1 : 2); return [$period, $time, $time] } } 

Here we use the Schwartz transform) to turn every minute into a three-element array consisting of the period number, the minute during this period and the original string. The result of this script is:

 22 45 45+3 46 90 90+3 
+2
source

In this particular case, as you described it, you can also (as someone answered but deleted again, it seems) convert your minutes of overtime to tenths and serial numbers:

 my @allinfogoals=qw(46 45+2 45 33 91 90+2); @allinfogoals=map { s/[.]/+/; $_ } sort { $a <=> $b } map { s/[+]/./; $_ } @allinfogoals; use Data::Dump; dd \@allinfogoals; 

... and then convert back. Output:

 [33, 45, "45+2", 46, "90+2", 91] 
0
source

All Articles