我有一个字典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
答案 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.chain
和print
语句进行广告宣传,并在一行中完成此操作:
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