迭代字典中的列表元素

时间:2018-01-21 12:21:13

标签: python list dictionary

我有一个字典dict = {1:['cup','pen'],2:['one','two'],3:['five']},其中我必须先遍历所有keys的第一个元素,然后再遍历第二个元素。 我已经用下面的方式写了,但是它的输出首先遍历列表index 0然后再遍历index 1。 任何人都可以帮我修改代码,以便它可以首先迭代所有列表的第一个元素和第二个元素

dict = {1:['cup','pen'],2:['one','two'],3:['five']}
for v in dict.values():
  for i in range (len(v)):
    print v[i]

输出上述代码:

cup
pen
one
two
five

但希望以下面的方式:

cup
one
five
pen
two

3 个答案:

答案 0 :(得分:3)

使用zipped-transpose idiom,将itertools.zip_longest压缩到最长的列表。然后迭代子列表中的每个项目,过滤掉None值。

from itertools import zip_longest

for i in zip_longest(*data.values()):
    for j in filter(None, i):
        print(j)

cup
one
five
pen
two

此处,data是您的输入词典。不要使用dict命名变量,它会以相同的名称隐藏内置类。

请注意,在python-3.6下面的python版本上不能保证这个顺序,因为在这些旧版本的python中没有对字典进行排序。

最后注意,对于python-2.x,要使用的适当函数是itertools.izip_longest

zip_longest的输出如下所示:

print(list(zip_longest(*data.values())))
[('cup', 'one', 'five'), ('pen', 'two', None)]

这些None值会被插入以代替缺失值,因为"拉链最长'功能的行为。这些None已被filter删除。

您可以使用此功能来使用itertools.chainprint语句进行广告宣传,并在一行中完成此操作:

from itertools import chain
print(*filter(None, chain.from_iterable(zip_longest(*data.values()))), sep='\n')

cup
one
five
pen
two

重写一点:

print(
   *filter(                                 # `filter` out None (iterable unpacking)       
        None, 
        chain.from_iterable(                # flatten an iterable of iterables
               zip_longest(*data.values())  # zip-longest transpose
       )
    ), 
    sep='\n'                                # separate unpacked arguments with newline
)

还有一个选项,用于家庭作业提交而没有zip_longest。这只是循环键,从每个列表一次弹出一个元素。

while any(bool(v) for v in data.values()):
    for k in data:
        try:
            print(data[k].pop(0))
        except IndexError:
            pass

cup
one
five
pen
two

这会清空其内容data,因此您可能需要预先复制数据。

答案 1 :(得分:3)

您可以尝试将字典中的每个列表转换为collections.deqeue()个对象,然后弹出每个队列中的第一个项目,直到所有队列都为空:

from collections import deque

d = {1:['cup','pen'],2:['one','two'],3:['five']}

# convert to deques
lsts = [deque(x) for x in d.values()]

# while lsts still has queues to pop
while lsts:

    # go over all the queues again
    for lst in lsts:

        # if it is not empty, pop it off and print it. 
        if len(lst) > 0:
            print(lst.popleft())

    # only keep queues that are not empty
    lsts = [x for x in lsts if x]

哪个输出:

cup
one
five
pen
two

在展示了这种可能的方法之后,它需要更多的工作才能产生你想要的东西,而@cᴏʟᴅsᴘᴇᴇᴅ的答案解决了如何轻松完成这项工作。

另请注意,您无需在此处使用collections.deque(),只需使用pop()从列表中弹出即可。为方便起见,我使用了O(1) popleft()函数。

您可以遇到的唯一效率问题是列表pop(0)O(n)。解决此问题的一种方法是事先撤消列表,然后调用pop(),这会导致O(1)行为。

答案 2 :(得分:1)

您可以在没有任何外部库的情况下尝试此操作:

dict = {1:['cup','pen'],2:['one','two'],3:['five']}



track={}

for i,ja in dict.items():
    for k,n in enumerate(ja):
        if k not in track:
            track[k]=[n]
        else:
            track[k].append(n)

for k in track.values():
    for m in k:
        print(m)

输出:

cup
one
five
pen
two