我正尝试按照以下示例说明的方式重新排序列表中的项目:
假设重新排序之前的列表是:
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
我想实现一个名为reorder_list(list, custom_order)
的方法,以便:
list1 = reorder_list(list1, [3, 6, 12, 9])
print(list1)
Out: [3, 6, 9, 1, 2, 4, 5, 7, 8, 10]
说明:[3, 6, 12, 9]
是我指定的自定义订单。 12
不在list1
,因此会被忽略。 3
,6
,9
位于list1
,因此它们会移到列表的前面,其顺序与[3, 6, 12, 9]
中的顺序相同。 list1
中的其余项目位于3
,6
,9
之后,并且按原始顺序排列。
是否有比实现类似C的循环代码更简单的方法(和Pythonic方式)。出于我的目的,我更关心代码简单而不是性能。
答案 0 :(得分:1)
def reorder_list(list_main, custom_order):
# initializing empty list
list1 = list()
# to add values of custom list to list1 which are present in main list
for value in custom_order:
# add only the values which are present in main list
if value in list_main:
list1.append(value)
# to add remaining element of main list to list1 which are not present in list1
for value in list_main:
if value not in list1:
list1.append(value)
return list1
list1 = [1,2,3,4,5,6,7,8,9,10]
list1 = reorder_list(list1, [3,6,12,9])
print(list1)
答案 1 :(得分:1)
对于这一点,一些列表推导应该具有合理的性能:
def reorder_list(list_to_reorder, custom_order):
new_list = [x for x in custom_order if x in set(list_to_reorder)]
new_list.extend(x for x in list_to_reorder if x not in set(custom_order))
return new_list
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(reorder_list(list1, [9, 6, 3, 12]))
[9, 6, 3, 1, 2, 4, 5, 7, 8, 10]
答案 2 :(得分:1)
def reorder_list(items, early):
moved = [item for item in early if item in items]
remain = [item for item in items if item not in moved]
return moved + remain
这与Gireesh和Stephen Rauch所写的算法完全相同。 Gireesh的版本是在列表推导之前编写的,而Stephen的版本使用集合进行更快的查找(但将两个输入列表转换为集合;一个应该足够)并使用生成器表达式扩展而不是分配第二个清单。
有一点值得注意的是,我们假设项目在列表中是唯一的。 in
和set
都期待这一点。
00sdf0的回答使用了一种非常不同的算法,它可能在Haskell中有意义,具有懒惰的评估和尾调用优化,但在这种情况下似乎既不易理解也不高效。使用切片可以更清楚地重写:
def reorder_list(items, early):
result = list(items)
for move in reversed(early):
try:
place = result.index(move)
result = [result[place]] + result[:place] + result[place+1:]
except ValueError:
pass # this item wasn't in the list
这确实会分配更多列表,每个移动项目有效地将列表复制两次。使用islice而不是slice生成了懒惰的评估,避免了其中一个副本。
答案 3 :(得分:0)
可以使用--help
和itertools.chain
以下列方式解决问题。
itertools.islice
输出:
from itertools import chain, islice
lst = [1,2,3,4,5,6,7,8,9,10]
items_to_move = [9,6,3,12]
# move index i to front of list
def front(seq, i):
item = islice(seq, i, i+1)
start = islice(seq, 0, i, None)
end = islice(seq, i+1, None)
return list(chain(item,start,end))
for item in reversed(items_to_move):
if item in lst:
lst = front(lst, lst.index(item))