Python3 中列表的自然排序
Natural sorting of a list in Python3
我正在尝试对列表进行排序:
[
'[fc] EDW Ratio (10 degrees)',
' [fc] EDW Ratio (45 degrees)',
' [fc] EDW Ratio (60 degrees)',
' [fc] EDW Ratio (25 degrees)',
' [fc] EDW Ratio (20 degrees)',
' [fc] EDW Ratio (30 degrees)',
' [fc] EDW Ratio (15 degrees)',
' [fc] EDW output factor (60 degrees)',
' [fc] Quality index'
]
使用已接受答案的第一部分here:
但列表的结尾是这样的:
[
' [fc] EDW Ratio (15 degrees)',
' [fc] EDW Ratio (20 degrees)',
' [fc] EDW Ratio (25 degrees)',
' [fc] EDW Ratio (30 degrees)',
' [fc] EDW Ratio (45 degrees)',
' [fc] EDW Ratio (60 degrees)',
' [fc] EDW output factor (60 degrees)',
' [fc] Quality index',
'[fc] EDW Ratio (10 degrees)'
]
而我希望 EDW 比率(10 度) 在排序后结束在列表的开头(索引位置 0) .
如何做到这一点?
我的代码包括以下内容:
#
# Method to define natural sorting used to sort lists
#
def atoi(text):
return int(text) if text.isdigit() else text
def natural_keys(text):
'''
alist.sort(key=natural_keys) sorts in human order
http://nedbatchelder.com/blog/200712/human_sorting.html
(See Toothy's implementation in the comments)
'''
return [ atoi(c) for c in re.split(r'(\d+)', text) ]
.
.
.
tname_list = test_names.split(",") # this outputs the exact first (unsorted) list shown above
tname_list.sort(key=natural_keys) # use human sorting defined above. This outputs the second list shown above.
您需要将 natural_keys
修改为仅 return 字符串的数字部分作为 int
。您应该使用 int()
进行转换,而不是 atoi()
,后者 return 是字符的 ascii 代码。
您的代码是正确的,但您的数据看起来不正确:所有条目都有一个前导空格,这意味着它们是"before"您认为最少的条目,实际上没有前导空格。
如果数据没有问题,我建议您修改代码以忽略前导空格(检查:How do I remove leading whitespace in Python?)。
如果您的任何字符串包含多个数字,或者将数字放在字符串的开头或结尾,您将 运行 陷入困境。那是因为 Python 无法将 int
和 str
相互比较。您的关键函数应该 return 既是元组又是列表。
def atoi(text):
return (int(text), '') if text.isdigit() else (math.nan, text)
math.nan
比较特殊,因为它永远不会小于实际数字。
我建议使用 natsort
(完全公开,我是作者)。您的数据也有点乱,您需要删除前导空格以规范化所有条目。
from natsort import natsorted
data = [
'[fc] EDW Ratio (10 degrees)',
' [fc] EDW Ratio (45 degrees)',
' [fc] EDW Ratio (60 degrees)',
' [fc] EDW Ratio (25 degrees)',
' [fc] EDW Ratio (20 degrees)',
' [fc] EDW Ratio (30 degrees)',
' [fc] EDW Ratio (15 degrees)',
' [fc] EDW output factor (60 degrees)',
' [fc] Quality index'
]
data_sorted = natsorted(data, key=lambda x: x.lstrip())
产出
[
'[fc] EDW Ratio (10 degrees)',
' [fc] EDW Ratio (15 degrees)',
' [fc] EDW Ratio (20 degrees)',
' [fc] EDW Ratio (25 degrees)',
' [fc] EDW Ratio (30 degrees)',
' [fc] EDW Ratio (45 degrees)',
' [fc] EDW Ratio (60 degrees)',
' [fc] EDW output factor (60 degrees)',
' [fc] Quality index',
]
import re
def get_numbers(texto):
return int(re.findall(r'[0-9]+', texto)[0])
def sort_list(l):
dicto = {}
for i in l:
dicto[get_numbers(i)] = i
lista = []
for i in sorted(list(dicto.keys())):
lista.append(dicto[i])
return lista
sort_list(frames)
请注意,它仅适用于第一个数字系列......“peter123jjj111”将仅考虑 123
我正在尝试对列表进行排序:
[
'[fc] EDW Ratio (10 degrees)',
' [fc] EDW Ratio (45 degrees)',
' [fc] EDW Ratio (60 degrees)',
' [fc] EDW Ratio (25 degrees)',
' [fc] EDW Ratio (20 degrees)',
' [fc] EDW Ratio (30 degrees)',
' [fc] EDW Ratio (15 degrees)',
' [fc] EDW output factor (60 degrees)',
' [fc] Quality index'
]
使用已接受答案的第一部分here:
但列表的结尾是这样的:
[
' [fc] EDW Ratio (15 degrees)',
' [fc] EDW Ratio (20 degrees)',
' [fc] EDW Ratio (25 degrees)',
' [fc] EDW Ratio (30 degrees)',
' [fc] EDW Ratio (45 degrees)',
' [fc] EDW Ratio (60 degrees)',
' [fc] EDW output factor (60 degrees)',
' [fc] Quality index',
'[fc] EDW Ratio (10 degrees)'
]
而我希望 EDW 比率(10 度) 在排序后结束在列表的开头(索引位置 0) .
如何做到这一点?
我的代码包括以下内容:
#
# Method to define natural sorting used to sort lists
#
def atoi(text):
return int(text) if text.isdigit() else text
def natural_keys(text):
'''
alist.sort(key=natural_keys) sorts in human order
http://nedbatchelder.com/blog/200712/human_sorting.html
(See Toothy's implementation in the comments)
'''
return [ atoi(c) for c in re.split(r'(\d+)', text) ]
.
.
.
tname_list = test_names.split(",") # this outputs the exact first (unsorted) list shown above
tname_list.sort(key=natural_keys) # use human sorting defined above. This outputs the second list shown above.
您需要将 natural_keys
修改为仅 return 字符串的数字部分作为 int
。您应该使用 int()
进行转换,而不是 atoi()
,后者 return 是字符的 ascii 代码。
您的代码是正确的,但您的数据看起来不正确:所有条目都有一个前导空格,这意味着它们是"before"您认为最少的条目,实际上没有前导空格。
如果数据没有问题,我建议您修改代码以忽略前导空格(检查:How do I remove leading whitespace in Python?)。
如果您的任何字符串包含多个数字,或者将数字放在字符串的开头或结尾,您将 运行 陷入困境。那是因为 Python 无法将 int
和 str
相互比较。您的关键函数应该 return 既是元组又是列表。
def atoi(text):
return (int(text), '') if text.isdigit() else (math.nan, text)
math.nan
比较特殊,因为它永远不会小于实际数字。
我建议使用 natsort
(完全公开,我是作者)。您的数据也有点乱,您需要删除前导空格以规范化所有条目。
from natsort import natsorted
data = [
'[fc] EDW Ratio (10 degrees)',
' [fc] EDW Ratio (45 degrees)',
' [fc] EDW Ratio (60 degrees)',
' [fc] EDW Ratio (25 degrees)',
' [fc] EDW Ratio (20 degrees)',
' [fc] EDW Ratio (30 degrees)',
' [fc] EDW Ratio (15 degrees)',
' [fc] EDW output factor (60 degrees)',
' [fc] Quality index'
]
data_sorted = natsorted(data, key=lambda x: x.lstrip())
产出
[
'[fc] EDW Ratio (10 degrees)',
' [fc] EDW Ratio (15 degrees)',
' [fc] EDW Ratio (20 degrees)',
' [fc] EDW Ratio (25 degrees)',
' [fc] EDW Ratio (30 degrees)',
' [fc] EDW Ratio (45 degrees)',
' [fc] EDW Ratio (60 degrees)',
' [fc] EDW output factor (60 degrees)',
' [fc] Quality index',
]
import re
def get_numbers(texto):
return int(re.findall(r'[0-9]+', texto)[0])
def sort_list(l):
dicto = {}
for i in l:
dicto[get_numbers(i)] = i
lista = []
for i in sorted(list(dicto.keys())):
lista.append(dicto[i])
return lista
sort_list(frames)
请注意,它仅适用于第一个数字系列......“peter123jjj111”将仅考虑 123