繁体   English   中英

在Python字典中遍历值列表

[英]iterating over values list in Python dictionary

嗨,我想遍历每个关键字都有值列表的Python字典,我想创建一个新的列表/字典来分隔每个值[x]或直接用分隔的值做事。

这是我拥有的字典的简化示例:

all_parameters = {"first": ["1a","1b","1c"], "second": ["2a","2b","2c"], "third": ["3a","3b","3c"]}

我正在寻找这样的值分开(通过创建一个新的字典或列表或直接用分开的值做事)。

grouped_parameters = [{"first": "1a", "second": "2a", "third": "3a"},
                      {"first": "1b", "second": "2b", "third": "3b"},
                      {"first": "1c", "second": "2c", "third": "3c"}]

我确保如何正确迭代每个key:value对。

i = 0
for k, v in all_parameters.items():
    for item in v:
        # stuck here
    i+=1

最终,我要执行的“工作”是将每个输出(例如,“ {{first”:“ 1a”,“ second”:“ 2a”,“ third”:“ 3a”}')转换为字符串,这样我可以将每个参数组发布到表中的单元格,因此理想情况下,我宁愿动态地执行此操作,而不是创建新的字典。

任何帮助将不胜感激。

假设所有列表的长度相同:

>>> length = len(next(all_parameters.itervalues()))
>>> [{k:v[i] for k,v in all_parameters.iteritems()} for i in range(length)]
[{'second': '2a', 'third': '3a', 'first': '1a'}, {'second': '2b', 'third': '3b', 'first': '1b'}, {'second': '2c', 'third': '3c', 'first': '1c'}]

在Python 3中,使用len(next(iter(all_parameters.values())))items而不是iteritems

(完成迭代器的恶作剧是因为如果只需要任意值列表的长度,则不需要所有字典值的列表。)

普通字典中的项目没有排序*,因此,如果要将字段转换为特定顺序,则在将字典转换为字符串时需要格外小心。

此代码使用一个元组,其中包含我们希望它们在输出dict字符串中出现的顺序的键字符串。

all_parameters = {
    "first": ["1a","1b","1c"], 
    "second": ["2a","2b","2c"], 
    "third": ["3a","3b","3c"],
}

# We want keys to be in this order
all_keys = ("first", "second", "third")

# Assumes all value lists are the same length.
for t in zip(*(all_parameters[k] for k in all_keys)):
    a = ['"{}": "{}"'.format(u, v) for u, v in zip(all_keys, t)]
    print('{' + ', '.join(a) + '}')

产量

{"first": "1a", "second": "2a", "third": "3a"}
{"first": "1b", "second": "2b", "third": "3b"}
{"first": "1c", "second": "2c", "third": "3c"}

这个怎么运作

我们首先使用生成器表达式(all_parameters[k] for k in all_keys) ,该表达式按all_keys指定的顺序从all_parameters中生成值列表。 我们使用* “ splat”运算符将这些列表作为args传递给zip 因此,对于您的示例数据,它相当于像这样调用zip

zip(["1a","1b","1c"], ["2a","2b","2c"], ["3a","3b","3c"])

zip有效地转换了传递给它的可迭代对象,因此该调用的结果是生成这些元组的迭代器:

('1a', '2a', '3a'), ('1b', '2b', '3b'), ('1c', '2c', '3c')

然后我们用for t in zip(...)for t in zip(...)逐个循环这些元组,因此在第一个循环中t获得值('1a', '2a', '3a') ,然后是('1b', '2b', '3b')等。

接下来,我们有一个列表推导,它将值字符串和相应的键字符串压缩在一起,并将它们格式化为在每个键和值字符串周围用双引号引起来的字符串。 然后,我们将这些字符串与逗号和空格作为分隔符连接在一起(并添加大括号字符)以构成最终的dict字符串。


*实际上,在Python 3.6中,普通字典确实会保留插入顺序,但这是当前的实现细节,因此不应依赖它。

如果列表的长度可能不同,则可以将mapNone一起使用,如下所示:

all_parameters = {"first": ["1a", "1b", "1c", "1d"], "second": ["2a", "2b", "2c"], "third": ["3a", "3b", "3c"]}

final = [dict(zip(all_parameters.keys(), values)) for values in map(None, *all_parameters.values())]

print final

map(None, *all_parameters.values())为您提供每个索引处每个键的值的元组-例如('1a', '2a', '3a') ,并将其压缩到键上并创建一个字典,我们得到所需的组合。

注意:这仅适用于Python 2.x,因为在3.x中更改了map 对于Python 3.x,我们可以使用itertools.zip_longest

from itertools import zip_longest

all_parameters = {"first": ["1a", "1b", "1c", "1d"], "second": ["2a", "2b", "2c"], "third": ["3a", "3b", "3c"]}

final = [dict(zip(all_parameters.keys(), values)) for values in zip_longest(*all_parameters.values())]

print(final)

在这两种情况下,我们得到:

[{'second': '2a', 'third': '3a', 'first': '1a'}, {'second': '2b', 'third': '3b', 'first': '1b'}, {'second': '2c', 'third': '3c', 'first': '1c'}, {'second': None, 'third': None, 'first': '1d'}]

我不确定这是否是您想要的

for i in range(len(all_parameters['first'])):
     for position in all_parameters:
         print(position+" "+all_parameters[position][i])

给出这样的输出

第一1a第二2a第三3a第一1b第二2b第三3b第一1c第二2c第三3c

仅当每个字典元素的列表大小与第一个列表大小相同时,此方法才有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM