Лучший способ отсортировать массив с необычным значением - PullRequest
4 голосов
/ 28 февраля 2012

У меня есть этот массив:

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

Я бы хотел отсортировать его по первому элементу '~'.Есть ли более элегантный способ решить эту проблему, нежели зацикливание и разбиение каждого значения?

Ответы [ 4 ]

5 голосов
/ 28 февраля 2012

Использование Преобразование Шварца :

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;
        },
    });

результат:

массив из 200 элементов:

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

массив из 2000 элементов:

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

массив из 20000 элементов:

       Rate SORT   ST
SORT 1.35/s   -- -73%
ST   4.96/s 266%   --
4 голосов
/ 28 февраля 2012

Сортировка и список фрагментов?

sort { ( split( /~/, $a ) )[0] <=> ( split( /~/, $b ) )[0] } @raw_stack;
2 голосов
/ 28 февраля 2012

Это может помочь. Они показывают, как извлечь части строк, чтобы использовать их для сортировки больших строк:

1 голос
/ 28 февраля 2012

Это всегда 6 цифр?Если это так, следующее будет самым простым и быстрым:

my @sorted_stack = sort @raw_stack;

Если нет,

my @sorted_stack =
   sort {
      my ($a_0) = split /~/, $a;
      my ($b_0) = split /~/, $b;
      $a_0 <=> $b_0
   } @raw_stack;

Преобразование Шварца может быть чище, если вы к этому привыкли, но на самом деле этомедленнее в этом случае: [ Обновление : по-видимому, это на самом деле быстрее, чем мое второе решение для больших списков.Хотя это никогда не быстрее, чем первый]

my @sorted_stack =
   map $_->[0],
    sort { $a->[1] <=> $b->[1] }
     map [ $_, split /~/ ],
      @raw_stack;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...