我想对每个字符串列表进行排序,例如:
list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
list2 = ['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002']
遵循模式[ '3DT1_S##', '3DT1_noPN_DIS3D_S##', '3DT1_PN_noDIS3D_S##', '3DT1_PN_DIS3D_S##']
结果应该是:
list1 = [ '3DT1_S001', '3DT1_noPN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_PN_DIS3D_S001']
list2 = [ '3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002']
我试着用排序的方法玩一下,但没有运气!
任何帮助?
答案 0 :(得分:3)
您可以定义以所需顺序返回元组的键函数,然后将函数传递给key
sorted
参数。
>>> def key_fn(x):
... tags = x.split('_')
... if tags[1][0] == 'S':
... return (0, int(tags[1][1:]))
... elif tags[1] == 'noPN':
... return (1, int(tags[3][1:]))
... elif tags[1] == 'PN':
... if tags[2] == 'noDIS3D':
... return (2, int(tags[3][1:]))
... else:
... return (3, int(tags[3][1:]))
...
>>> list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
>>> sorted(list1, key=key_fn)
['3DT1_S001', '3DT1_noPN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_PN_DIS3D_S001']
答案 1 :(得分:2)
我的两分钱......它有一个'patternList'变量来定义顺序。这可能是实现这一目标的最简单(最易读,最易扩展)的方式:没有杂乱的if-elses。此外,具有相同起始模式的列表项按字符串的其余部分排序。
list1.sort(key = myKey)
表示对于每个列表项myKey
函数在排序之前执行。 myKey
函数修改排序列表项仅用于排序目的,其方式是普通排序可以执行您想要的操作。在输出排序列表中,不使用原始列表项(不是myKey
修改过的。)
在下面的示例中,myKey函数将列表项拆分为两部分,并根据patternList变量使用整数标记第一部分。正常排序可以以您想要的方式处理返回的元组。
list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
list2 = ['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002', '3DT1_PN_DIS3D_S003', '3DT1_PN_DIS3D_S001']
def myKey(x):
# create the 'order list' for starting pattern
patternsList = [ '3DT1_S', '3DT1_noPN_DIS3D_S', '3DT1_PN_noDIS3D_S', '3DT1_PN_DIS3D_S']
for i in range(len(patternsList)): # iterate patterns in order
pattern = patternsList[i]
if x.find(pattern) == 0: # check if x starts with pattern
# return order value i and x without the pattern
return (i, x.replace(pattern, ''))
# if undefined pattern is found, put it to first
return (-1, x)
# alternatively if you want undefind to be last
# return (len(patternList)+1, x)
print list1
list1.sort(key = myKey)
print list1
print list2
list2.sort(key = myKey)
print list2
答案 2 :(得分:0)
此方法通过按找到的第一个模式的索引进行排序。
>>> import re
>>> list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
>>> list2 = ['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002']
>>> patterns = [ '3DT1_S', '3DT1_noPN_DIS3D_S', '3DT1_PN_noDIS3D_S', '3DT1_PN_DIS3D_S']
>>> pattern = '|'.join('(%s)'%x for x in patterns)
>>> pattern #Creates a regex pattern with each pattern as a group in order
'(3DT1_S)|(3DT1_noPN_DIS3D_S)|(3DT1_PN_noDIS3D_S)|(3DT1_PN_DIS3D_S)'
>>> def sort_key(x):
return re.match(pattern,x).lastindex
>>> list1, list2 = [sorted(l, key=sort_key) for l in (list1,list2)]
>>> list1
['3DT1_S001', '3DT1_noPN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_PN_DIS3D_S001']
>>> list2
['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002']
答案 3 :(得分:-1)
这是一种方法,它采用一系列“前缀”,用于在排序之前对列表进行分组。每个项目都会添加到与 first 对应的组中,并且只会添加到匹配的第一个前缀。
list1 = ['3DT1_PN_DIS3D_S001', '3DT1_PN_noDIS3D_S001', '3DT1_S001', '3DT1_noPN_DIS3D_S001']
list2 = ['3DT1_noPN_DIS3D_S002', '3DT1_PN_noDIS3D_S002', '3DT1_PN_DIS3D_S002', '3DT1_S002']
prefixes = [ '3DT1_S', '3DT1_noPN_DIS3D_S', '3DT1_PN_noDIS3D_S', '3DT1_PN_DIS3D_S']
def f(l):
result = []
for p in prefixes: # for each prefix, in order
a = [] # items in the group
b = [] # items not in the group
for x in l: # for each item
if x.startswith(p): # does the item match the prefix?
a.append(x) # add it to the group
else:
b.append(x) # add it to the "rest"
result.append(sorted(a)) # sort the group and save it for the result
l = b # continue with the non-group elements
return result
这是结果:
>>> f(list1)
[['3DT1_S001'], ['3DT1_noPN_DIS3D_S001'], ['3DT1_PN_noDIS3D_S001'], ['3DT1_PN_DIS3D_S001']]
>>> f(list2)
[['3DT1_S002'], ['3DT1_noPN_DIS3D_S002'], ['3DT1_PN_noDIS3D_S002'], ['3DT1_PN_DIS3D_S002']]