What is single-line with low computational complexity to return the two largest array values?

This is more like “I wonder if this is possible” than the question “I really need”, but anyway: I know if I want the smallest value in the list using custom function comparison, I can do this easily with List::Util::reduce.

my $biggest = reduce {comparison($a, $b) ? $b:$a} @myArray;

But if I want the two biggest values ​​in this array? Again, just one traversal of the array.

I can do this by writing a loop for, but I would really like to have another perlish lining.


Edit: with just one bypass of the array, I meant that the computational complexity would not be greater than O(n). Sorting all articles is not so efficient, since I don’t need to sort everything, just the two biggest values.

But I probably ask too much :)

+5
source share
4 answers

To find the maximum two values ​​of the list, you can either iterate over the values ​​with two variables to hold the maximums:

my @list = qw(3 1 2 5 9 7 8 6 4);

my ($x, $y) = (0, 0);

($x, $y) = $_ > $x ? ($_, $x) :
           $_ > $y ? ($x, $_) : next for @list;

say "$x $y";  # '9 8'

or you can use the fold to reduce the list:

use List::Util 'reduce';

my $max = reduce {
    $b > $$a[0] ? [$b, $$a[0]] : 
    $b > $$a[1] ? [$$a[0], $b] : $a
} [0, 0], @list;

say "@$max"; # '9 8'

, - , - . , , , . , O(n)

+4

(sort { compare($b, $a) } @array)[0 .. 1] - , , @array. , , .

reduce, - , , , " ":)

+4
my @biggest_two = ( sort { $b <=> $a } @myArray )[0..1]
+1

. , , comparison($a,$b).

, , >, , , , a > b b > c, a > c, . , , , . , OR, OR, . , script.

#!/usr/bin/perl

use strict;
use warnings;

use List::Util 'shuffle';

my @array = shuffle (1..10);
my @out = (0,0); #(max, second)

map { $_>$out[0] ? ( unshift @out, $_ and pop @out) : $_>$out[1] ? $out[1] = $_ : () } @array;

print "$_\n" for @out;

, . , , , .

, . , - , . , sort . Perl , , , , .

-1

All Articles