我是一般的编程新手,所以希望在这里真正扩展我的技能。我正在尝试编写一个脚本,它将从对象中获取字符串列表,然后根据我的设计模板对它们进行排序。不在模板中的任何项目都将添加到最后。
以下是我现在正在做的事情,但是有人会建议更好/更有效的方法吗?
originalList = ['b', 'a', 'c', 'z', 'd']
listTemplate = ['a', 'b', 'c', 'd']
listFinal = []
for thing in listTemplate:
if thing in originalList:
listFinal.append(thing)
originalList.pop(originalList.index(thing))
for thing in originalList:
listFinal.append(thing)
originalList.pop(originalList.index(thing))
答案 0 :(得分:2)
试试这个:
originalList = ['b', 'a', 'c', 'z', 'd']
listTemplate = ['a', 'b', 'c', 'd']
order = { element:index for index, element in enumerate(listTemplate) }
sorted(originalList, key=lambda element: order.get(element, float('+inf')))
=> ['a', 'b', 'c', 'd', 'z']
这是它的工作原理:
listTemplate
中的每个元素指示其相对于其他元素的相对顺序。例如,a
为0
,b
为1
,依此类推originalList
进行排序。如果order
字典中存在其中一个元素,则使用其相对位置进行排序。如果它不存在,则返回正无限值 - 这将保证不在listTemplate
中的元素最终会结束,而不会在它们之间进一步排序。问题中的解决方案虽然正确,但并不是非常pythonic。特别是,每当您必须构建新列表时,请尝试使用列表推导而不是显式循环/追加。并且“破坏”输入列表并不是一个好习惯(在这种情况下使用pop()
)。
答案 1 :(得分:1)
您可以使用listTemplate
列表创建一个字典,这样可以将昂贵的(O(N)
)list.index
操作简化为O(1)
次查找。
>>> lis1 = ['b', 'a', 'c', 'z', 'd']
>>> lis2 = ['a', 'b', 'c', 'd']
使用enumerate
创建一个带有项目作为键的dict(考虑到项目是可以清除的)并将索引作为值。
>>> dic = { x:i for i,x in enumerate(lis2) }
现在dic
看起来像:
{'a': 0, 'c': 2, 'b': 1, 'd': 3}
现在对于lis1
中的每个项目,我们需要在dic中检查它的索引,如果找不到密钥,我们会返回float('inf')
。
用作key
的函数:
def get_index(key):
return dic.get(key, float('inf'))
现在对列表进行排序:
>>> lis1.sort(key=get_index)
>>> lis1
['a', 'b', 'c', 'd', 'z']
答案 2 :(得分:0)
最后一步,你可以使用:
listFinal += originalList
它会将这些项添加到最后。
答案 3 :(得分:0)
这是一种具有更好计算复杂性的方法:
# add all elements of originalList not found in listTemplate to the back of listTemplate
s = set(listTemplate)
listTemplate.extend(el for el in originalList if el not in s)
# now sort
rank = {el:index for index,el in enumerate(listTemplate)}
listFinal = sorted(originalList, key=rank.get)
答案 4 :(得分:0)
根本不需要创建新词典:
>>> len_lis1=len(lis1)
>>> lis1.sort(key = lambda x: lis2.index(x) if x in lis2 else len_lis1)
>>> lis1
['a', 'b', 'c', 'd', 'z']