Python字典中对值列表的迭代

3

你好,我想迭代一个Python字典,其中每个键都有一个值列表,我想要创建一个新列表/字典,将每个值[x]分开,或者直接处理分离后的值。

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

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

我希望将数值分离,可以通过创建新的字典或列表,也可以直接对分离后的数值进行操作。请注意不要删除 HTML 标签。
grouped_parameters = [{"first": "1a", "second": "2a", "third": "3a"},
                      {"first": "1b", "second": "2b", "third": "3b"},
                      {"first": "1c", "second": "2c", "third": "3c"}]

我不确定如何正确地遍历每个键值对。

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

最终我要做的事情是将每个输出(例如 '{"first": "1a", "second": "2a", "third": "3a"}')转换为字符串,以便我可以将每个参数组发布到表格中的单元格中,因此最好是动态执行此操作,而不是创建一个新的字典。

非常感谢您提供任何帮助。


1
值列表的长度是否总是相同的?如果不是,您希望如何处理短列表? - PM 2Ring
另外,请记住,dict 中的项目没有顺序,因此如果您希望字段按特定顺序排列,则在将 dict 转换为字符串时需要小心。 - PM 2Ring
4个回答

3

假设所有列表长度相同:

>>> 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。(这种迭代器的操作是因为如果你只想要任意值列表的长度,你不需要一个所有字典值的列表。)

1
一个普通字典中的项目是没有顺序的*,因此在将字典转换为字符串时,如果想要字段按照特定顺序排列,就需要小心处理。
这段代码使用了一个元组,其中包含我们希望输出的字典字符串中键的字符串顺序。
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"运算符将这些列表作为参数传递给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(...)循环遍历这些元组,因此在第一次循环中,t的值为('1a', '2a', '3a'),然后是('1b', '2b', '3b')等等。
接下来,我们有一个列表推导式,它将值字符串与相应的键字符串一起压缩,并将它们格式化为一个带有双引号的字符串。然后,我们使用逗号和空格作为分隔符(并添加大括号字符)将这些字符串连接在一起,以生成我们最终的字典字符串。
实际上,在Python 3.6中,普通字典确实保留插入顺序,但这目前仅是一项实现细节,不应依赖于此。

1
如果列表长度可能不同,您可以使用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,因为map在3.x中发生了变化。对于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'}]

0

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接