2015-03-31 220 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

相关问题