2015-03-31 125 views
4

我對python非常陌生,我正在尋找一種方法來對數字前的單詞進行排序。對python列表進行排序以使字母出現在數字前

我知道你可以使用排序做到以下幾點:

a = ['c', 'b', 'd', 'a'] 
a.sort() 
print(a) 
['a', 'b', 'c', 'd'] 

b = [4, 2, 1, 3] 
b.sort() 
print(b) 
[1, 2, 3, 4] 

c = ['c', 'b', 'd', 'a', 4, 2, 1, 3] 
c.sort() 
print(c) 
[1, 2, 3, 4, 'a', 'b', 'c', 'd'] 

但是我想排序c生產:提前

['a', 'b', 'c', 'd', 1, 2, 3, 4] 

感謝

+2

警告:你的第三個例子也不會在Python 3工作。相反,你會得到'TypeError:無法定型的類型:int() Kevin 2015-03-31 16:37:55

回答

6

你可以提供一個自定義的key參數,它給字符串賦予的值比它輸入的值低:

>>> c = ['c', 'b', 'd', 'a', 4, 2, 1, 3] 
>>> c.sort(key = lambda item: ([str,int].index(type(item)), item)) 
>>> c 
['a', 'b', 'c', 'd', 1, 2, 3, 4] 
+2

'[0,1] [type(item)== int]' – thefourtheye 2015-03-31 16:44:33

+0

如果在列表中存在除str或int之外的其他類型,則失敗並返回「IndexError」。 – dawg 2015-03-31 18:08:38

+0

@dawg,true。如果你想要更多的類型,你可以將它們添加到'[str,int]'列表中。或者你甚至可以用'lambda item:({str:0,int:1} .get(type(item),2),item)'替換它,並讓所有非字符串非ints排序到右邊。 – Kevin 2015-03-31 18:12:41

1
[sorted([letter for letter in c if isinstance(letter, str)]) + \ 
sorted([number for number in c if isinstance(number, int)]] 

應該這樣做。

+0

是的,它很早,我沒有喝咖啡,所以我認爲這些數字也是用引號括起來的。但現在已經修復了。 – 2015-03-31 16:44:47

3

默認的Python排序是asciibetical

考慮:

>>> c = ['c', 'b', 'd', 'a', 'Z', 0, 4, 2, 1, 3] 

默認的排序是:

>>> sorted(c) 
[0, 1, 2, 3, 4, 'Z', 'a', 'b', 'c', 'd'] 

它也不會在所有的Python3工作:

Python 3.4.3 (default, Feb 25 2015, 21:28:45) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> c = ['c', 'b', 'd', 'a', 'Z', 0, 4, 2, 1, 3] 
>>> sorted(c) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unorderable types: int() < str() 

解決方案是創建一個帶有索引整數的元組作爲第一個元素(基於項目類型),並將項目本身作爲下一個元素。 Python 2和3將使用第二個元素異構類型對元組進行排序。

考慮:

>>> c = ['c', 'b', 'd', 'a', 'Z', 'abc', 0, 4, 2, 1, 3,33, 33.333] 

注意字符,整數,字符串的混合物,浮

def f(e): 
    d={int:1, float:1, str:0} 
    return d.get(type(e), 0), e 

>>> sorted(c, key=f) 
['Z', 'a', 'abc', 'b', 'c', 'd', 0, 1, 2, 3, 4, 33, 33.333] 

或者,如果你想有一個拉姆達:基於

>>> sorted(c,key = lambda e: ({int:1, float:1, str:0}.get(type(e), 0), e))) 
['Z', 'a', 'abc', 'b', 'c', 'd', 0, 1, 2, 3, 4, 33, 33.333] 

來自「狼」的評論,你也可以這樣做:

>>> sorted(c,key = lambda e: (isinstance(e, (float, int)), e)) 
['Z', 'a', 'abc', 'b', 'c', 'd', 0, 1, 2, 3, 4, 33, 33.333] 

我必須承認比較好...

+2

這與Python的多態性不一致:你應該允許像int那樣行爲的任何對象被視爲一個對象,而不是通過使用'type'來強制它 - 使用'isinstance'來代替派生類是一貫對待。 – 2015-03-31 18:50:10

0

您還可以使用cmp PARM:

c = ['c', 'b', 'd', 'a', 4, 2, 1, 3] 

def compare_function(a, b): 
    if isinstance(a, str) and isinstance(b, int): 
     return -1 
    if isinstance(a, int) and isinstance(b, str): 
     return 1 
    return cmp(a, b) 

c.sort(cmp=compare_function) 
+1

em ...'cmp'是一種不贊成的。但你總是可以通過'functools.cmp_to_key'將cmp函數轉換爲鍵。 – HuStmpHrrr 2015-03-31 17:01:56

1

比方說,我們有一個混合列表如下:

c = ['s', 'a',2 , 'j', 9, 'e', 11, 't', 'k', 12, 'q'] 

首先,我們需要將列表分成兩個單獨的部分(字符串和整數),將它們排序然後將它們附加到最後。下面是做這件事:

>>> c = sorted([i for i in c if not str(i).isdigit()]) + sorted([i for i in c if str(i).isdigit()]) 

現在,您可以:

>>> c 
['a', 'e', 'j', 'k', 'q', 's', 't', 2, 9, 11, 12] 
1

如果您有混合的ASCII和數字類型的列表,你需要確定什麼是numeric對象類型。您可以使用Numbers抽象基類,以確定哪些是一個數字(int, float, long, complex)類,包括所有的派生類的一個實例(bool, Decimal, Franctions等):

>>> from numbers import Number 
>>> [isinstance(n, Number) for n in (0,1.1,0j,True,'a')] 
[True, True, True, True, False] 

一旦你知道什麼是一個數字的情況下,您可以使用Python布爾創建一個主清單鍵,並將清單項本身作爲輔助鍵(即,包含[(True, 1.1), (False, 'abc'), etc]的元組)False將以低於True的順序排序,正如0 < 1以典型的升序排序,因此就是我們想要的。

將其應用於您的列表(擴大)爲例:

>>> c = ['c', 'b', 'd', 'a', 4, 2, 1, 35, 1.1, 6L, 'aac', True] 
>>> sorted(c, key=lambda e: (isinstance(e, Number), e)) 
['a', 'aac', 'b', 'c', 'd', 1, True, 1.1, 2, 4, 6L, 35] 

需要注意的是不同的數值類型是否被正確排序(1<=True<1.1<6L<35

相關問題