我有一个字符串列表,可以表示整数和名称。 默认字符串比较执行以下操作:
sorted(['1','2','3','4','10','102','14','Alice','John','Sally'])
['1', '10', '102', '14', '2', '3', '4', 'Alice', 'John', 'Sally']
我想按如下方式对列表进行排序:
['1', '2', '3', '4', '10', '14', '102', 'Alice', 'John', 'Sally']
表示:
我尝试过比较方法,但我不知道如何干净地确定字符串是否代表一个没有try / except的整数?
提前致谢
答案 0 :(得分:10)
如果没有负数:
lyst = ['1','2','3','4','10','102','14','Alice','John','Sally']
print sorted(lyst, key=lambda k: int(k) if k.isdigit() else k)
这是一个不依赖于CPython细节并与Python 3一起使用的版本:
sorted(lyst, key=lambda k: (0, int(k)) if k.isdigit() else (1, k))
这里的关键是一个元组。对于数字或文本,元组中的第一项为0或1,这使得数字在文本之前排序。然后元组中的第二个项是值,这会使值在其组内适当地排序。我最初使用float("+inf")
来使文本项在数字后排序,但这种方法(受Tom Zych的回答启发)更简单,更快。
如果您希望字符串排序不区分大小写,请添加.lower()
:
sorted(lyst, key=lambda k: (0, int(k)) if k.isdigit() else (1, k.lower()))
答案 1 :(得分:5)
以下适用于Python 2和Python 3:
l = ['1','2','3','4','10','102','14','Alice','John','Sally','33']
num, alpha = [], []
[num.append(elem) if elem.isdigit() else alpha.append(elem) for elem in l]
result = sorted(num, key=int) + sorted(alpha)
print(result)
它通过对列表进行分区来避免将字符串与int进行比较。避免这种比较的原因是它是not fully specified(Python 2)或禁止(Python 3)。
答案 2 :(得分:5)
这应该适用于具有关键功能的sort
版本。
def sortkey(s):
try:
n = int(s)
return (0, n)
except ValueError:
return (1, s)
答案 3 :(得分:0)
我会选择比较功能:
import types
def cmp_func(val1, val2):
# is val1 an integer?
try:
val1 = int(val1)
except ValueError:
pass # val1 is no integer
try:
val2 = int(val2)
except ValueError:
pass #val2 is no integer
if type(val1) == types.IntType and type(val2) == types.IntType:
return cmp(val1, val2)
elif type(val1) == types.StringType and type(val2) == types.IntType:
# firstly strings, afterwards integer values
return -1
elif type(val1) == types.IntType and type(val2) == types.StringType:
# firstly strings, afterwards integer values
return 1
else:
return cmp(val1, val2)
if __name__ == "__main__":
my_list = ['1', '10', '102', '14', '2', '3', '4', 'Alice', 'John', 'Sally']
my_list.sort(cmp_func)
print(my_list)