在python中使用相同的键合并两个列表字典

时间:2014-10-14 23:11:07

标签: python list dictionary

我的问题:

我试图将两个列表词典合并到一个新词典中,为每个键交替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]

5 个答案:

答案 0 :(得分:3)

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根据此处接受的答案构建:Making a flat list out of list of lists in Python

答案 1 :(得分:2)

您可以使用itertools或列出切片here来执行此操作。使用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该键的合并结束。

答案 2 :(得分:2)

要替换xy迭代插入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)

Example

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'}

答案 3 :(得分:1)

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的值包含更多元素,代码都能正常工作。

答案 4 :(得分:1)

与发布的其他解决方案类似,但我会将其中的一部分移至功能

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总是比{{1}短一个})。

如果你有一个不支持dict理解的旧python版本,你可以使用它来代替

strings