对包含带有 SI 前缀的数字的字符串列表进行排序
Sort a list of strings that contain numbers with SI prefixes
我正在尝试对以下列表进行排序:
['default.smt',
'Setup 19k Hz.smt',
'Setup 1k Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt']
其中 k
是 1000,所以例如 9k
是 9000,并且应该出现在 19k
之前,即 19000。
所以我需要我的列表如下所示:
['default.smt',
'Setup 3 Hz.smt',
'Setup 55 Hz.smt',
'Setup 500 Hz.smt',
'Setup 1k Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt',
'Setup 19k Hz.smt']
'default.smt'
单元格可以是第一个或最后一个,我不介意。
我该怎么做?
您可以在自定义键函数中使用正则表达式。在示例中,我使用了一个在某些边缘情况下会失败的朴素正则表达式,但您可以对其进行调整。
import re
regex = re.compile(r'(\d+)(k)?')
li = ['default.smt',
'Setup 19k Hz.smt',
'Setup 1k Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt']
def magic(e):
match = regex.findall(e)
if not match:
return -1
num, k = int(match[0][0]), match[0][1]
if k:
return num * 1000
return num
print(sorted(li, key=magic))
产出
['default.smt',
'Setup 3 Hz.smt',
'Setup 55 Hz.smt',
'Setup 500 Hz.smt',
'Setup 1k Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt',
'Setup 19k Hz.smt']
我是用replace()
函数做的。您可以在不导入的情况下制作此代码。这是我的代码:
def sortList(list):
sortedList = []
finalList = []
for elements in list:
if elements == "default.smt":
finalList.append(elements)
else:
elements = elements.replace("Setup ", "")
elements = elements.replace("k", "000")
elements = elements.replace("Hz.smt", "")
sortedList.append(int(elements))
sortedList.sort()
for elements in sortedList:
elements = str(elements).replace("000", "k")
finalList.append("Setup " + str(elements) + " Hz.smt")
return finalList
list = ['default.smt',
'Setup 19k Hz.smt',
'Setup 1k Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt']
print(sortList(list))
输出如下:
['default.smt', 'Setup 3 Hz.smt', 'Setup 55 Hz.smt', 'Setup 500 Hz.smt', 'Setup 1k Hz.smt', 'Setup 5k Hz.smt', 'Setup 9k Hz.smt', 'Setup 19k Hz.smt']
这个答案基本上是 copy/pasted 来自 the examples section of natsort
's documentation。我所做的只是更改细节。
>>> import re
>>> import natsort
>>>
>>> # Define how each unit will be transformed
>>> conversion_mapping = {
... "k": 1000, # kilo
... "M": 1000000, # mega
... # Extend suffixes as you need
... }
>>>
>>> # This regular expression searches for numbers and units
>>> all_units = "|".join(conversion_mapping.keys())
>>> float_re = natsort.numeric_regex_chooser(natsort.FLOAT | natsort.SIGNED)
>>> unit_finder = re.compile(r"({})({})".format(float_re, all_units), re.IGNORECASE)
>>>
>>> def unit_replacer(matchobj):
... """
... Given a regex match object, return a replacement string where units are modified
... """
... number = matchobj.group(1)
... unit = matchobj.group(2)
... new_number = float(number) * conversion_mapping[unit]
... return "{}".format(new_number)
...
>>> # Demo time!
>>> data = ['default.smt',
... 'Setup 19k Hz.smt',
... 'Setup 1k Hz.smt',
... 'Setup 3 Hz.smt',
... 'Setup 500 Hz.smt',
... 'Setup 55 Hz.smt',
... 'Setup 5k Hz.smt',
... 'Setup 9k Hz.smt']
>>> [unit_finder.sub(unit_replacer, x) for x in data]
['default.smt',
'Setup 19000.0 Hz.smt',
'Setup 1000.0 Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5000.0 Hz.smt',
'Setup 9000.0 Hz.smt']
>>>
>>> natsort.natsorted(data, key=lambda x: unit_finder.sub(unit_replacer, x), alg=natsort.LOWERCASEFIRST)
['default.smt',
'Setup 3 Hz.smt',
'Setup 55 Hz.smt',
'Setup 500 Hz.smt',
'Setup 1k Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt',
'Setup 19k Hz.smt']
这里的优势在于,这不仅使用了 natsort
的强大算法,而且您还可以使用 natsort
的浮点数正则表达式定义,is very thorough .
完全公开,我是 natsort 的作者。
我正在尝试对以下列表进行排序:
['default.smt',
'Setup 19k Hz.smt',
'Setup 1k Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt']
其中 k
是 1000,所以例如 9k
是 9000,并且应该出现在 19k
之前,即 19000。
所以我需要我的列表如下所示:
['default.smt',
'Setup 3 Hz.smt',
'Setup 55 Hz.smt',
'Setup 500 Hz.smt',
'Setup 1k Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt',
'Setup 19k Hz.smt']
'default.smt'
单元格可以是第一个或最后一个,我不介意。
我该怎么做?
您可以在自定义键函数中使用正则表达式。在示例中,我使用了一个在某些边缘情况下会失败的朴素正则表达式,但您可以对其进行调整。
import re
regex = re.compile(r'(\d+)(k)?')
li = ['default.smt',
'Setup 19k Hz.smt',
'Setup 1k Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt']
def magic(e):
match = regex.findall(e)
if not match:
return -1
num, k = int(match[0][0]), match[0][1]
if k:
return num * 1000
return num
print(sorted(li, key=magic))
产出
['default.smt',
'Setup 3 Hz.smt',
'Setup 55 Hz.smt',
'Setup 500 Hz.smt',
'Setup 1k Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt',
'Setup 19k Hz.smt']
我是用replace()
函数做的。您可以在不导入的情况下制作此代码。这是我的代码:
def sortList(list):
sortedList = []
finalList = []
for elements in list:
if elements == "default.smt":
finalList.append(elements)
else:
elements = elements.replace("Setup ", "")
elements = elements.replace("k", "000")
elements = elements.replace("Hz.smt", "")
sortedList.append(int(elements))
sortedList.sort()
for elements in sortedList:
elements = str(elements).replace("000", "k")
finalList.append("Setup " + str(elements) + " Hz.smt")
return finalList
list = ['default.smt',
'Setup 19k Hz.smt',
'Setup 1k Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt']
print(sortList(list))
输出如下:
['default.smt', 'Setup 3 Hz.smt', 'Setup 55 Hz.smt', 'Setup 500 Hz.smt', 'Setup 1k Hz.smt', 'Setup 5k Hz.smt', 'Setup 9k Hz.smt', 'Setup 19k Hz.smt']
这个答案基本上是 copy/pasted 来自 the examples section of natsort
's documentation。我所做的只是更改细节。
>>> import re
>>> import natsort
>>>
>>> # Define how each unit will be transformed
>>> conversion_mapping = {
... "k": 1000, # kilo
... "M": 1000000, # mega
... # Extend suffixes as you need
... }
>>>
>>> # This regular expression searches for numbers and units
>>> all_units = "|".join(conversion_mapping.keys())
>>> float_re = natsort.numeric_regex_chooser(natsort.FLOAT | natsort.SIGNED)
>>> unit_finder = re.compile(r"({})({})".format(float_re, all_units), re.IGNORECASE)
>>>
>>> def unit_replacer(matchobj):
... """
... Given a regex match object, return a replacement string where units are modified
... """
... number = matchobj.group(1)
... unit = matchobj.group(2)
... new_number = float(number) * conversion_mapping[unit]
... return "{}".format(new_number)
...
>>> # Demo time!
>>> data = ['default.smt',
... 'Setup 19k Hz.smt',
... 'Setup 1k Hz.smt',
... 'Setup 3 Hz.smt',
... 'Setup 500 Hz.smt',
... 'Setup 55 Hz.smt',
... 'Setup 5k Hz.smt',
... 'Setup 9k Hz.smt']
>>> [unit_finder.sub(unit_replacer, x) for x in data]
['default.smt',
'Setup 19000.0 Hz.smt',
'Setup 1000.0 Hz.smt',
'Setup 3 Hz.smt',
'Setup 500 Hz.smt',
'Setup 55 Hz.smt',
'Setup 5000.0 Hz.smt',
'Setup 9000.0 Hz.smt']
>>>
>>> natsort.natsorted(data, key=lambda x: unit_finder.sub(unit_replacer, x), alg=natsort.LOWERCASEFIRST)
['default.smt',
'Setup 3 Hz.smt',
'Setup 55 Hz.smt',
'Setup 500 Hz.smt',
'Setup 1k Hz.smt',
'Setup 5k Hz.smt',
'Setup 9k Hz.smt',
'Setup 19k Hz.smt']
这里的优势在于,这不仅使用了 natsort
的强大算法,而且您还可以使用 natsort
的浮点数正则表达式定义,is very thorough .
完全公开,我是 natsort 的作者。