我正在使用Zigzag Iterator进行编程,它将以以下方式迭代2D列表:
[1,4,7]
[2,5,8,9]
[3,6]
到
[1,2,3,4,5,6,7,8,9]
我实现了一个算法:
class ZigzagIterator:
def __init__(self, vecs):
self.vecs = []
self.turns = 0
for vec in vecs:
vec and self.vecs.append(iter(vec))
def next(self):
try:
elem = self.vecs[self.turns].next()
self.turns = (self.turns+1) % len(self.vecs)
return elem
except StopIteration:
self.vecs.pop(self.turns)
if self.hasNext():
self.turns %= len(self.vecs)
def hasNext(self):
return len(self.vecs) > 0
if __name__ == "__main__":
s = ZigzagIterator([[1,4,7],[2,5,8,9],[3,6]])
while s.hasNext():
print s.next()
>>> 1 2 3 4 5 6 7 8 None None 9 None
我知道问题是因为我在每个列表的next()上再调用1次,然后得到3个None。我可以通过使用Java检查hasnext方法来解决此问题。我还可以在python中实现hasnext迭代器。我的问题是我如何能以更Python的方式解决此问题,而不是用Java来思考。
答案 0 :(得分:3)
这是itertools
docs中的循环食谱。
attr
答案 1 :(得分:1)
这可以使用itertools
中的工具轻松构建:
from itertools import zip_longest, chain
sentinel = object()
def zigzag(lists):
return (
value
for value
in chain.from_iterable(zip_longest(*lists, fillvalue=sentinel))
if value is not sentinel
)
lists = [
[1,4,7],
[2,5,8,9],
[3,6],
]
print(list(zigzag(lists)))
需要sentinel
的东西,以便可以将None
的值安全地压缩成Z字形。 (应该保证此值不会出现在原始列表中。)
答案 2 :(得分:1)
from itertools import chain, zip_longest
print([i for i in chain.from_iterable(zip_longest([1,4,7], [2,5,8,9], [3,6])) if i is not None])
这将输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
答案 3 :(得分:1)
对于pythonic解决方案,您需要实现迭代器协议,我希望这正是您想要的。
from itertools import chain, zip_longest
class ZigZagIterator:
def __init__(self, *lists):
self.elements = chain(*zip_longest(*lists))
def __iter__(self):
for num in self.elements:
if num is not None:
yield num
zig = ZigZagIterator([1, 4, 7], [2, 5, 8, 9], [3, 6])
for num in zig:
print(num)
如果您确实要使用has_next
和next
,那么
from itertools import chain, zip_longest
class ZigZagIterator:
def __init__(self, *lists):
elements = chain(*zip_longest(*lists))
self.elements = filter(lambda x: x is not None, elements)
def has_next(self):
try:
self.next_value = next(self.elements)
except StopIteration:
return False
return True
def next(self):
return self.next_value
zig = ZigZagIterator([1, 4, 7], [2, 5, 8, 9], [3, 6])
while zig.has_next():
print(zig.next())