我的问题:
我试图将两个列表词典合并到一个新词典中,为每个键交替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]
答案 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)
要替换x
,y
迭代插入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'}
答案 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