2013-02-06 103 views
9

我正在尝试执行以下操作。我有一个预定义的列表,用作给定列表中的“order by”。如何按给定顺序对列表进行排序?

my @orderby = ('car', 'boat', 'chicken', 'cat', 'dog', 'mouse'); 
    or 
my %orderby = ('car' => 0, 'boat' => 1, 'chicken' => 2, 'cat' => 3, 'dog' => 4, 'mouse' => 5); 

my @list = ('boat', 'car', 'mouse', 'chicken'); 

我尝试了无数的方法来排序它,我没有得到我想要的。我在谷歌上搜索过,但在这里,但我没有找到答案。

@list需要以这种方式进行排序:

sort @list using %orderby 

,我排序后要打印:

car, boat, chicken, mouse 

BTW,@list可以有重复的条目:

my @list = ('boat', 'car', 'mouse', 'chicken', 'mouse', 'car');

在这种情况下,打印需要是:

car, car, boat, chicken, mouse, mouse

你们有解决方案吗? 或者其他方法。 谢谢!

+1

回复您的更新,我解决方案处理重复。 – ikegami

+0

是的,我测试过了! Thx再次! – Jonathan

回答

12
my @orderby = qw(car boat chicken cat dog mouse); 
my @list = qw(boat car mouse chicken); 

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

my @sorted = sort { $orderby{$a} <=> $orderby{$b} } @list; 

或者,如果你想惹人们的思想,

my @orderby = qw(car boat chicken cat dog mouse); 
my @list = qw(boat car mouse chicken); 

my %counts; ++$counts{$_} for @list; 
my @sorted = map { ($_) x ($counts{$_}||0) } @orderby; 
+1

要排序的数组是'list',而不是'orderby'。 – Toto

+0

哎呀,错字。固定。 – ikegami

+0

哦,我很快。现在我将尝试了解地图。谢谢! – Jonathan

0

当然,如果你有为了所有潜在项目的列表,以及你需要的产品的一个小名单选择,那么这实际上是一个选择问题,而不是一个排序问题?

my %items = map { $_ => 1 } @list; 
my @items = grep { $items{$_} } @orderby; 

奔跑在O(n)的时间,而不是为O(n log n)的太:)

+0

这与我在4天前发布的解决方案中的第二个基本相同,除了我的更好,因为它处理重复,而您的规则不符合OP的规范,因为它没有。 – ikegami

0

基数排序是这种情况下,一个不错的选择:

use Sort::Key::Radix qw(ukeysort); 
@sorted = ukeysort { $orderby{$_} } @data; 
相关问题