簡體   English   中英

在python中使用相同的鍵合並兩個列表字典

[英]merging two dictionaries of lists with the same keys in python

我的問題:

我正在嘗試將兩個列表詞典合並到一個新詞典中,為每個鍵交替2個原始列表的元素,以創建該鍵的新列表。

例如,如果我有兩個詞典:

strings = {'S1' : ["string0", "string1", "string2"], 'S2' : ["string0", "string1"]}

Ns = {'S1' : ["N0", "N1"], 'S2' : ["N0"]}

我想合並這兩個詞典,以便最終字典看起來像:

strings_and_Ns = {'S1': ["string0", "N0", "string1", "N1", "string2"], 'S2': ["string0", "N0", "string1"]}

或者更好的是,讓列表中的字符串為每個鍵連接在一起,例如:

strings_and_Ns = {'S1': ["string0N0string1N1string2"], 'S2': ["string0N0string1"]}

(我正在嘗試將DNA序列片段連接在一起。)

到目前為止我嘗試過的:

壓縮

 for S in Ns:   
     newsequence = [zip(strings[S], Ns[S])]
     newsequence_joined = ''.join(str(newsequence))
     strings_and_Ns[species] = newsequence_joined

這不會將序列連接成一個字符串,並且字符串的順序仍然不正確。

使用defaultdict

from collections import defaultdict
strings_and_Ns = defaultdict(list)

    for S in (strings, Ns):
        for key, value in S.iteritems():
        strings_and_Ns[key].append(value)

這個字符串的順序也是不正確的......

以某種方式移動每個鍵的列表......

for S in strings: 
    list = strings[S]
    L = len(list)
    for i in range(L):
        strings_and_Ns[S] = strings_and_Ns[S] + strings[S][i] + strings[S][i]
strings_and_Ns = {}
for k,v in strings.items():
    pairs = zip(v, Ns[k] + ['']) # add empty to avoid need for zip_longest()
    flat = (item for sub in pairs for item in sub)
    strings_and_Ns[k] = ''.join(flat)

flat是根據這里接受的答案構建的: 在Python中列出列表中的平面列表

您可以使用itertools此處所述的列表切片來完成此操作 使用itertools,結果看起來很聰明。

strings_and_Ns = {}
for skey, sval in strings.iteritems():
    iters = [iter(sval), iter(Ns[skey])]
    strings_and_Ns[skey] = ["".join(it.next() for it in itertools.cycle(iters))]

您必須注意列表的相應長度。 如果一個迭代器引發StopIteration ,則該鍵的合並結束。

要交替xy迭代插入default值的default值:

from itertools import izip_longest

def alternate(x, y, default):
    return (item for pair in izip_longest(x, y, default) for item in pair)

a = {'S1' : ["string0", "string1", "string2"], 'S2' : ["string0", "string1"]}
b = {'S1' : ["N0", "N1"], 'S2' : ["N0"]}
assert a.keys() == b.keys()
merged = {k: ''.join(alternate(a[k], b[k], '')) for k in a}
print(merged)

產量

{'S2': 'string0N0string1', 'S1': 'string0N0string1N1string2'}

itertools.izip_longest將處理不均勻的長度列表,然后使用str.join連接成一個單獨的字符串。

strings = {'S1' : ["string0", "string1", "string2"], 'S2' : ["string0", "string1"]}

Ns = {'S1' : ["N0", "N1"], 'S2' : ["N0"]}

from itertools import izip_longest as iz

strings_and_Ns = {k:["".join([a+b for a, b in iz(strings[k],v,fillvalue="")])] for k,v in Ns.items()}

print(strings_and_Ns)
{'S2': ['string0N0string1'], 'S1': ['string0N0string1N1string2']}

這與以下相同:

strings_and_Ns  = {}
for k, v in Ns.items():
     strings_and_Ns[k] = ["".join([a + b for a, b in iz(strings[k], v, fillvalue="")])]

使用izip_longest意味着無論哪個dict的值包含更多元素,代碼都將起作用。

與發布的其他解決方案類似,但我會將其中的一部分移到一個函數中

import itertools   

def alternate(*iters, **kwargs):
    return itertools.chain(*itertools.izip_longest(*iters, **kwargs))

result = {k: ''.join(alternate(strings[k], Ns[k] + [''])) for k in Ns}
print result

得到:

{'S2': 'string0N0string1', 'S1': 'string0N0string1N1string2'}

alternate功能來自https://stackoverflow.com/a/2017923/66349 它將iterables作為參數並連續地將每個項鏈接在一起(使用izip_longest作為Padraic Cunningham所做的)。

您可以指定fillvalue=''來處理不同的長度列表,或者只是手動填充較短的列表,如上所述(假設Ns總是比strings短一個)。

如果你有一個不支持dict理解的舊python版本,你可以使用它

result = dict((k, ''.join(alternate(strings[k], Ns[k] + ['']))) for k in Ns)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM