参考已排序的数组对数组进行排序

时间:2013-09-20 21:51:32

标签: arrays perl sorting

我有一个包含所有可能元素的引用数组,并按自定义顺序排序,而不是字母数字排序。例如,

@ref_array = ('one','two','three','four','five','six');

现在所有输入数组都需要根据引用数组的顺序进行排序。输入数组将始终是引用数组的子集。

@in1 = ('three','one','five');  # Input
@out1 = ('one','three','five'); # Desired Output

@in2 = ('six','five','four','three','two','one'); # Input
@out2 = ('one','two','three','four','five','six') # Desired Output

4 个答案:

答案 0 :(得分:10)

my %h = map { $ref_array[$_] => $_ } 0 .. $#ref_array;

my @out1 = @ref_array[ sort { $a <=> $b } @h{@in1} ];
my @out2 = @ref_array[ sort { $a <=> $b } @h{@in2} ];

%h持有key =&gt;像one =&gt;这样的val对0two =&gt; 1等等。

@h{@in1}2,0,4哈希切片,它被排序,数组切片@ref_array[0,2,4]one, three, five

答案 1 :(得分:4)

这并不复杂。

第1步,我们需要从您的值到Perl可以排序的某个键的映射,例如数字。我们可以使用自定义归类数组中元素的索引,如:

my %custom_value = map { $ref_array[$_] => $_ } 0 .. $#ref_array;

第2步,我们在您的输入上执行 Schwartzian转换,其中一个上述值为关键:

my @out =
  map  { $_->[1] }
  sort { $a->[0] <=> $b->[0] }
  map  {[ $custom_value{$_} => $_ ]}
       @in;

答案 2 :(得分:1)

对于使用小整数键进行排序,基数排序通常是具有O(N)复杂度的更快解决方案:

use Sort::Key::Radix qw(ukeysort);

my @ref = ('one','two','three','four','five','six');
my %ref = map { $ref[$_] => $_ } 0..$#ref;

my @out = ukeysort { $ref{$_} } @in;

或者您也可以使用便宜的O(N)计数排序:

my %ref;
$ref{$_}++ for @in;
no warnings 'uninitialized';
my @out = map { ($_) x $ref{$_} } @ref;

答案 3 :(得分:0)

所有呈现的解决方案都显示O(NlogN)时间复杂度的排序。有一种方法可以在没有实际排序的情况下进行,因此O(N)时间复杂度。

sub custom_usort {
    my %h;
    @h{@_} = ();
    grep exists $h{$_}, ('one','two','three','four','five','six');
}

修改

如果输入中有多个值,则有此解决方案:

sub custom_sort {
    my %h;
    $h{$_}++ for @_;
    no warnings 'uninitialized';
    map {($_) x $h{$_}} ('one','two','three','four','five','six');
}