![](/img/trans.png)
[英]How to move list items to the front if they are in another list while keeping the order
[英]Python - reordering items in list by moving some items to the front while keeping the rest in the same order
我試圖以以下示例所示的方式對列表中的項目重新排序:
假設重新排序之前的列表是:
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
我想實現一種稱為reorder_list(list, custom_order)
的方法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的循環代碼更簡單的方法(和Python方式)。 就我的目的而言,我更關心代碼的簡單性而不是性能。
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)
為此,應該有一些列表理解能力:
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]
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中可能是有意義的,但在這種情況下,似乎既不容易理解也不高效。 使用slice可以更清楚地重寫它:
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產生的懶惰評估避免了那些副本之一。
可以使用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))
輸出:
[9, 6, 3, 1, 2, 4, 5, 7, 8, 10]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.