通过遍历字典创建列表

4

我定义了一个字典,类似如下(list是整数列表):

my_dictionary = {'list_name' : list, 'another_list_name': another_list}

现在,我想通过迭代这个字典来创建一个新的列表。最终,我希望它看起来像这样:
my_list = [list_name_list_item1, list_name_list_item2, 
                list_name_list_item3, another_list_name_another_list_item1]

等等,

我的问题是:我该如何实现这个功能?

我尝试过

for key in my_dictionary.keys():
    k = my_dictionary[key]
    for value in my_dictionary.values():
        v = my_dictionary[value]
        v = str(v)
        my_list.append(k + '_' + v)

但是在这个例子的第4行,我收到了一个类型错误(不可哈希类型:'list')而不是期望的输出。

6个回答

5

您正在尝试通过其值获取字典项,而您已经拥有该值。

使用列表推导式在一行中完成:


```python [item for item, value in your_dict.items() if value == your_value] ```
my_dictionary = {'list_name' : [1,4,5], 'another_list_name': [6,7,8]}

my_list = [k+"_"+str(v) for k,lv in my_dictionary.items() for v in lv]

print(my_list)

结果:

['another_list_name_6', 'another_list_name_7', 'another_list_name_8', 'list_name_1', 'list_name_4', 'list_name_5']

请注意,由于字典中的顺序不能保证,因此列表的顺序也无法保证。您可以通过按键对项目进行排序来修复顺序:
my_list = [k+"_"+str(v) for k,lv in sorted(my_dictionary.items()) for v in lv]

非常感谢您的帮助!我对Python还比较新,所以非常感谢您的解释和解决方案! :) - Hisushi

2

试试这个:

my_list = []
for key in my_dictionary:
    for item in my_dictionary[key]:
        my_list.append(str(key) + '_' + str(item))

希望这能有所帮助。

0
你已经写了一个针对键的外层循环,然后是一个针对值的内层循环,并尝试将每个值用作键,这就是程序失败的原因。只需使用字典的items方法来迭代键值对即可:
["{}_{}".format(k,v) for k,v in d.items()]

哎呀,无法解析所需的格式;我们应该逐个生成内部列表中的每个项目。不用担心...

d={1:[1,2,3],2:[4,5,6]}
list(itertools.chain(*(
      ["{}_{}".format(k,i) for i in l]
      for (k,l) in d.items() )))

这个有点复杂。我们再次从字典中获取键值对,然后在值上进行内部循环,并将其格式化为字符串。这会产生内部序列,因此我们使用chain和*将其展平,最后将结果保存为一个列表。

编辑:事实证明,Python 3.4.3在执行嵌套的生成器表达式时会变得非常混乱;我不得不将内部表达式转换为列表,否则它会在执行格式化之前替换一些k和l的组合。

再次编辑:正如某人在已删除的答案中发布的(这让我感到困惑),我过于复杂了。您可以在链接的推导式中进行扁平嵌套:

["{}_{}".format(k,v) for k,l in d.items() for v in l]

这个方法也是由Jean-François Fabre发布的。


0
你现在的问题是dict().values()返回的是一个生成器,它会产生字典中的值而不是键,所以当你尝试在第4行进行查找时,它会失败(在这种情况下),因为字典中的值不能用作键。在另一种情况下,比如{1:2, 3:4},它会抛出一个KeyError,而{1:2, 2:1}则不会引发错误,但可能会导致混乱的行为。
至于你实际的问题,列表不像字典那样给数据命名,它们只是简单地存储索引。
def f()
    a = 1
    b = 2
    c = 3
    l = [a, b, c]

    return l

调用f()将返回[1, 2, 3],任何关于abc的概念都将完全丢失。

如果您想简单地连接字典中的列表,复制第一个列表,然后调用.extend()即可:

my_list = my_dictionary['list_name'][:]
my_list.extend(my_dictionary['another_list_name'])

如果您想保留列表项的顺序,同时仍然通过名称引用它们,请查看collections中的OrderedDict类

不是values()是一个生成器,而是值不是键。在这种情况下,它们是列表,而列表是不可哈希的,因此不能作为键使用,所以他会得到类型错误而不是键错误。 - Yann Vernier
我表达不清楚,应该是说“是”而不是“返回”。 - Adam Barnes

0

使用列表推导式就像这样

d = {"test1":[1,2,3,],"test2":[4,5,6],"test3":[7,8,9]}

new_list = [str(item[0])+'_'+str(v) for item in d.items() for v in item[1]]

输出:

new_list:
['test1_1',
 'test1_2',
 'test1_3',
 'test3_7',
 'test3_8',
 'test3_9',
 'test2_4',
 'test2_5',
 'test2_6']

0

让我们初始化我们的数据

In [1]: l0 = [1, 2, 3, 4]

In [2]: l1 = [10, 20, 30, 40]

In [3]: d = {'name0': l0, 'name1': l1}

请注意,在我的示例中,与您的不同,列表的内容不是字符串...列表不是异构容器吗?
也就是说,您不能简单地连接键和列表项,最好使用str(...)内置函数将这些值转换为字符串。
现在,解决您的问题...我使用了一个带有两个循环的列表推导式,外部循环首先遍历字典中的项(即键-值对),内部循环其次遍历相应列表中的项。
In [4]: res = ['_'.join((str(k), str(i))) for k, l in d.items() for i in l]

In [5]: print(res)
['name0_1', 'name0_2', 'name0_3', 'name0_4', 'name1_10', 'name1_20', 'name1_30', 'name1_40']

In [6]: 

在你的情况下,使用str(k)+'_'+str(i)也可以,但是当前连接具有固定'text'的字符串的习语是使用'text'.join(...)方法。请注意,.join接受一个单一参数,即可迭代对象,在列表推导式中我使用join((..., ...))来将连接元素收集到一个单一参数中。

附言:正如其他答案中所说,您无法保证在外部循环中检索到的“k,l”项的任何特定顺序。 - gboffi

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