[英]Combine list elements by suffix
給出兩個帶后綴的列表:
l1 = ['C_1', 'B_1', 'A']
l2 = ['B_2', 'C_2', 'D']
我想像這樣組合它們:
['C_1', 'C_2', 'B_1', 'B_2', 'A', 'D']
元素將與l1
組合作為錨點。 這意味着,如果C_*
位於l1
B_*
之前,則輸出中將保留相同的順序。 此外,具有相同前綴C_*
元素將按后綴的遞增順序組合在一起。 如上所示,帶有后綴的元素按它們出現的順序放置。
您可以假設l1
中的所有元素都具有后綴_1
,而l2
所有元素都具有后綴_2
。
我試過這個:
from collections import OrderedDict
from itertools import chain
o = OrderedDict()
for x in l1 + l2:
o.setdefault(x.split('_')[0], []).append(x)
result = list(chain.from_iterable(o.values()))
哪個有效,但想知道是否有更簡潔的方法來做到這一點。
編輯:
后綴只是元素出現在哪個列表中的一個標准。假設我從l1
有C_1
,從l2
C_2
,那么C_*
元素基於l1
出現在l1
,並且在l2
中出現在最終列表中(所以,它是... C_1, C_2...
)。
此外, l1
和l2
中的所有元素彼此獨特且彼此獨立。 希望有所幫助。
Alex答案很短,但使用了具有O(n)
復雜度的list.index
。
我建議使用構建p
作為字典進行小修改,反轉迭代以模擬index
工作方式(否則當出現多於1次時返回最后的索引)。
在這種情況下,排序鍵函數使用dict查找,速度更快:
l1 = ['C_1', 'B_1', 'A']
l2 = ['B_2', 'C_2', 'D']
p = {s[0]:i for i,s in reversed(list(enumerate(l1 + l2)))}
print(sorted(l1 + l2, key=lambda x: (p[x[0]], x)))
使用itertools.groupby()
和sorted()
函數:
import itertools
l1 = ['C_1', 'B_1', 'A']
l2 = ['B_2', 'C_2', 'D']
l1_len = len(l1)
groups_gen = (list(g) for k,g in itertools.groupby(sorted(l1+l2), key=lambda x: x[0] or '_' not in x))
result = list(itertools.chain.from_iterable(sorted(groups_gen,
key=lambda x: l1.index(x[0]) if x[0] in l1 else l1_len)))
print(result)
輸出:
['C_1', 'C_2', 'B_1', 'B_2', 'A', 'D']
按照其前綴出現在l1
的索引對所有元素進行排序,使用字符串的其余部分來斷開關系:
p = [s[0] for s in l1 + l2]
print(sorted(l1 + l2, key=lambda x: (p.index(x[0]), x)))
p
使用l1
和l2
前綴,以便p.index(x[0])
不會引發錯誤。
你可以簡單地用這種方法做
l1 = ['C_1', 'B_1', 'A']
l2 = ['B_2', 'C_2', 'D']
首先選擇所有第一個常用詞項
new=[y for item in l1 for item2 in l2 for y in [item] + [item2] if item[0]==item2[0]]
注意我在上面的列表理解中使用了extend。
現在只需找到除第一個字母的常用項目之外剩余的項目:
for item1 in l2:
for item2 in l1:
if item1 not in new:
new.append(item1)
elif item2 not in new:
new.append(item2)
print(new)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.