Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way to sort an array with unusual value

Tags:

arrays

perl

I have this array:

@raw_stack = (
    '900244~dfasdf~ddd3',
    '900122~dfasdf~ddd1',
    '900244~dfasdf~ddd2',
    '900456~dfasdf~ddd4',
    '900312~dfasdf~ddd3',
    '900456~dfasdf~ddd5',
    );

I'd like to sort it by the first '~' element. Is there a more elegant way to solve this rather than looping and splitting through each value?

like image 713
cr8ivecodesmith Avatar asked Dec 16 '22 03:12

cr8ivecodesmith


2 Answers

Use Schwartzian transform:

my @raw_stack = (
    '900244~dfasdf~ddd3',
    '900122~dfasdf~ddd1',
    '900244~dfasdf~ddd2',
    '900456~dfasdf~ddd4',
    '900312~dfasdf~ddd3',
    '900456~dfasdf~ddd5',
);
my @sorted = 
    map { $_->[0] }
    sort { $a->[1] <=> $b->[1] }
    map { [$_, (split/~/)[0]] } @raw_stack;
dump@sorted;

Benchmark:

#!/usr/bin/perl 
use 5.010;
use strict;
use warnings;
use Benchmark qw(:all);


my $s = '~dfasdf~ddd3';
my @arr = ();
for(0..20000) {
    push @arr, int(rand(100000)) . $s;
}
my $count = -3;
cmpthese($count, {
        'ST' => sub {
            my @sorted = 
                map { $_->[0] }
                sort { $a->[1] <=> $b->[1] }
                map { [$_, (split/~/)[0]] } @arr;
        },
        'SORT' => sub {
            my @sorted =
                sort {
                    my ($a_0) = split /~/, $a;
                    my ($b_0) = split /~/, $b;
                    $a_0 <=> $b_0
                } @arr;
        },
    });

result:

array of 200 elements:

      Rate SORT   ST
SORT 267/s   -- -61%
ST   689/s 158%   --

array of 2000 elements:

       Rate SORT   ST
SORT 18.0/s   -- -71%
ST   61.5/s 242%   --

array of 20000 elements:

       Rate SORT   ST
SORT 1.35/s   -- -73%
ST   4.96/s 266%   --
like image 85
Toto Avatar answered Jan 14 '23 02:01

Toto


Sort and list slices?

sort { ( split( /~/, $a ) )[0] <=> ( split( /~/, $b ) )[0] } @raw_stack;
like image 41
Oesor Avatar answered Jan 14 '23 01:01

Oesor