2013-02-06 102 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; 
相關問題