[英]Combine two lists of strings
給定兩個包含重復項的字符串列表,每個列表中都保存一個元素,您如何將二者組合成一個列表,每個列表按列表順序包含每個值的一個副本?
例如,給定以下兩個Python列表:
a = ['Second', 'Third', 'Fourth']
b = ['First', 'Second', 'Third']
要么
a = ['First', 'Third', 'Fourth']
b = ['First', 'Second', 'Third']
您如何將兩個列表結合起來得到一個列表,如下所示:
result = ['First', 'Second', 'Third', 'Fourth']
請注意,不一定必須信任字符串的確切值才能幫助元素排序。
我知道有些情況下可能沒有確定的方法將列表鎖定為特定順序,並且可能需要對它們進行特殊處理,但是對於一般情況,我寧願遵循以下程序。 例如:
a = ['First', 'Third', 'Fourth']
b = ['First', 'Second', 'Fourth']
可以同時使用'Third'
和'Second'
,因為它們之間的兩個列表中都沒有提供指導的項目。
編輯:我應該進一步解釋字符串,因為我看到你們中的許多人都假設我只能對兩個列表進行原始合並排序,而這行不通。
我正在使用故事標題,對於每個故事,它們僅列出其他部分,而不列出鏈接的故事本身。 因此,通過列出兩個列表(我不確定,可能還有更多),我可以拿出完整的分期付款清單,以按適當順序排列它們。
簡單算法:
碼:
def order_list(lst, order_dict):
return sorted(list(lst), key = lambda x: order_dict.get(x, -1))
c = list(set(a + b))
ord_dict = {"First": 1, "Second": 2, "Third": 3, "Fourth": 4}
order_list(c, ord_dict)
您在這里有2個不同的問題:
我會分開做。 消除重復非常簡單。 使用一set
:
>>> a = ['Second', 'Third', 'Fourth']
>>> b = ['First', 'Second', 'Third']
>>> x = set(a)
>>> x
set(['Second', 'Fourth', 'Third'])
>>> x.update(b)
>>> x
set(['Second', 'Fourth', 'Third', 'First'])
然后,您需要以某種方式定義順序。 最簡單的方法是將每個可能的元素映射到一個值:
>>> order_dict = {'First': 1, 'Second': 2, 'Third': 3, 'Fourth': 4}
>>> result = sorted(list(x), key=lambda i: order_dict[i])
>>> result
['First', 'Second', 'Third', 'Fourth']
另外,如果可以為值定義一個比較功能,則可以對sorted
的cmp
參數使用某種比較功能。
希望這可以幫助。
如果我們假設您的兩個列表都是有序的,並且它們每個都只缺少整個集合中的某些元素,那么我可以看到一種算法在大多數情況下都可以使用 。
這是該算法的python代碼:
a1 = ['Second', 'Third', 'Fourth']
b1 = ['First', 'Second', 'Third']
a2 = ['First', 'Third', 'Fourth']
b2 = ['First', 'Second', 'Third']
a3 = ['First', 'Third', 'Fourth']
b3 = ['First', 'Second', 'Fourth']
def merge(a, b):
c = []
b_oldindex = 0
for a_index in range(len(a)):
match = False
for b_index in range(b_oldindex, len(b)):
if a[a_index] == b[b_index]:
c.extend(b[b_oldindex:b_index+1])
b_oldindex = b_index + 1
match = True
break
if not match:
c.append(a[a_index])
if b_oldindex < len(b):
c.extend(b[b_oldindex:])
return c
print(merge(a1,b1))
print(merge(a2,b2))
print(merge(a3,b3))
print(merge(b1,a1))
print(merge(b2,a2))
print(merge(b3,a3))
產生以下輸出:
['First', 'Second', 'Third', 'Fourth']
['First', 'Second', 'Third', 'Fourth']
['First', 'Third', 'Second', 'Fourth']
['First', 'Second', 'Third', 'Fourth']
['First', 'Second', 'Third', 'Fourth']
['First', 'Second', 'Third', 'Fourth']
在所有測試用例中,唯一無法產生正確順序的測試用例是merge(a3,b3)
。
徹底解決問題可能涉及實現正確的合並算法 (如merge sort中所用 ),該算法需要能夠評估元素應處於的順序。您可以在Rosetta代碼上看到python的實現 。
更新:
鑒於這實際上是對一組書籍中的分期付款進行排序,因此可以通過考慮其他信息來避免在第三組數據中描述的情況。 即,以與版權或發布日期相反的順序在列表上使用merge
功能。
例如,在您的情況下:
a3 = ['First', 'Third', 'Fourth'] # Second novel
b3 = ['First', 'Second', 'Fourth'] # Third novel
a3
的書本應該早於b3
的書出版。 如果可以收集這種元數據,則可以避免此問題。
同一本書的不同版本之間的版權日期不會有所不同,但出版日期可能會有所不同。 因此,我將在出版日期之前查看版權日期。
set
容器是通過其中沒有重復項來定義的。 您可以同時創建兩個列表,然后將其強制轉換回列表類型:
a = ['Second', 'Third', 'Fourth']
b = ['First', 'Second', 'Third']
c= list(set(a+b))
['Second', 'Fourth', 'Third', 'First']
#Note that set will not organize anything, it will just delete the duplicates
我有同樣的問題,我也有答案。 我找到了這篇文章,是因為我正在尋找更多的pythonic方法。
首先,有關特殊情況的注釋:
a=['A','C','D','E']
b=['A','B','D','F']
c=joinListsOrdered(a,b)
就我而言,我沒有任何問題: ['A','B','C','D','E','F']
和['A','C','B','D','F','E']
。 我想要的唯一驗證條件是: c
中元素的順序分別遵守a
和b
的順序,即[el for el in c if el in a]
在元素方面等於a
(並等效於b
)。 我也認為,這是對此問題的唯一合理立場,而無需進一步了解此問題。
這就是說:重點是公共元素( ['A', 'D']
)。 如果這些順序正確,則其他所有內容很容易卡在中間。 因此,此算法:
def joinListsOrdered(a,b):
# Find ORDERED common elements
order={}
for i, e in enumerate(a):
order[e]=i
commonElements=sorted(set(a) & set(b), key=lambda i: order[i])
# Cycle on each common element.
i=0 #index of a
j=0 #index of b
c=[]
for comEl in commonElements:
while not a[i]==comEl:
c.append(a[i])
i=i+1
while not b[j]==comEl:
c.append(b[j])
j=j+1
c.append(comEl)
i=i+1;j=j+1
# Add the eventual residuals after the last common element.
c=c+a[i:]+b[j:]
return c
當然,如果某個公共元素的a
和b
的順序不同,它就不會遵守驗證條件,但是在那種情況下,問題沒有解決的辦法。
在最簡單的情況下,只有一個不同的元素並且它處於相同的位置,只是通過兩個字符串進行迭代連接
newlist = []
for i in range(len(a)):
if a[i] == b[i]:
newlist.append(a)
else:
newlist.append(a)
newlist.append(b)
如果您的列表比較復雜,請先將其中一個列表變成字典,然后在合並時對照另一個列表。
使用Python的bisect庫。
from bisect import insort
a = ['First', 'Third', 'Fourth']
b = ['First', 'Second', 'Fourth']
for entry in b:
insort(entry, a)
unique = Set(a)
print unique
注意:很明顯,字符串無法正確地進行比較,您可能需要為此使用字典!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.