2011-11-03 53 views
6

我有一系列的名單,看起來像這樣:在Python中使用自定義排序參數排序列表的最佳方式是什麼?

li1 = ['a.1', 'b.9', 'c.8', 'd.1', 'e.2'] 
li2 = ['a.4', 'b.1', 'c.2', 'd.2', 'e.4'] 

我如何重新安排在每個列表中,這樣的第一個項目是「b.something」的項目?對於上面的示例:

li1 = ['b.9', 'a.1', 'c.8', 'd.1', 'e.2'] 
li2 = ['b.1', 'a.4', 'c.2', 'd.2', 'e.4'] 

在第一項不重要後維護訂單。謝謝您的幫助。

+0

我不確定,但是這個問題可能會對你感興趣:http://stackoverflow.com/questions/2436607/how-to-use-re-match-objects-in-a-list-comprehension –

+0

只是想知道爲什麼每個人都用's.startwith('b')',而不是'[0] =='b''。有沒有什麼性能優勢?如果不是,我想保存我的大腦的長期記憶使用。 – yosukesabai

+0

@yosukesabai:只有一個答案使用's.startwith('b')'。其他人使用's.startwith('b。')'就像在問題中要求的那樣。 –

回答

4

重新排列項目中的每個列表中,這樣的第一個項目是「b.something」

維護訂單後的第一項是不重要的。

那是不排序,然後。從概念上講,你只是想把這個元素放在前面。

換句話說,您需要一個由該元素組成的列表,後面跟着不是該元素的所有元素。對於存在多個b.something s的情況稍加修改,注意我們不關心發生了什麼,只要第一個元素是b.something,我們可以重新說明:滿足條件的每個元素的列表(「開始與b.「),其次是每個不符合條件的元素。 (這有時被稱爲分區;參見例如std::partition在C++)

在Python,這是爲描述這兩個列表的組件與列表解析和粘在一起它們作爲簡單:

[x for x in li if x.startswith('b.')] + [x for x in li if not x.startswith('b.')] 

......或者你可以假裝你正在排序,只是在應用了key之後,只有一些元素只有兩個值,並應用相應的key,如Ignacio Vasquez-Abrams的回答。

+0

這是最接近請求。無論如何,我不知道「排序」的速度有多快,因爲您必須使用相同的函數來讀取列表兩次以進行過濾。 –

+0

哇,這很酷。出於某種原因,加入列表解析一起從未發生過。謝謝。 – drbunsen

+0

@Joël兩次讀取列表只會導致恆定因子開銷。排序是O(n lg n),因爲'sort'需要能夠任意排序,因此必須做某種基於比較的排序,而每個過濾列表理解過程通常被看作O(n)。 –

3

您可以使用sorted,接受一個key參數,並返回一個列表:

>>> li1 = ['a.1', 'b.2', 'c.8'] 
>>> def k(s): 
...  if s.startswith('b.'): 
...   return 1 
...  else: 
...   return 2 
... 
>>> sorted(li1, key=k) 
['b.2', 'a.1', 'c.8'] 

k應返回的東西,可以迭代項目之間進行比較。

注意:sort更改輸入就地並不返回任何內容,當sorted返回排序列表並且不修改您的列表。兩者都以相同的方式工作。

5

Python的排序是穩定的,所以你會保持第一個項目後的順序無論。

li1.sort(key=lambda x: not x.startswith('b.')) 
+1

這非常漂亮,但我想有些人會認爲「顯式比隱式更好」意味着您不應該將布爾值視爲可比較的值(「False

相關問題