我有一个迭代器,该迭代器由多个相同大小的列表组成。为了我的目的,我需要知道这些列表中至少一个的长度。但是与迭代器一样,不能以与普通数组相同的方式访问它们。所以我的想法是通过说出这样的长度:
for i in iter:
list_len = len(i)
break
这是可行的,但是,当以后使用此列表并想要再次对其进行循环时,它将跳过第一次迭代,并且基本上从上一个循环(上一个循环)的下一个迭代继续进行。
有什么办法可以解决这个问题?或者,pythonic的实现方式是什么? 我在想/正在阅读这样做:
from itertools import tee
iter_tmp, iter = tee(iter)
for i in iter_tmp:
list_len = len(i)
break
是的,这也行得通,因为我现在可以使用原始的iter
供以后使用,但是我不得不做一个循环,导入itertools之类的东西只是为了弄清楚它的长度,这让我的眼睛很痛。迭代器中的列表。但是也许这只是解决问题的方法?
更新
只是想进一步解释我在做什么。
因为这样的迭代不是列表或数组,但就我而言,如果我遍历迭代器,我会得到类似的信息(如果迭代器中有四个“列表”):>
>>> for i in iter_list:
print(i)
[1, 2, 5, 3]
[3, 2, 5, 8]
[6, 8, 3, 7]
[1, 4, 6, 1]
现在,迭代器中的所有“列表”都具有相同的长度,但是由于列表本身是通过许多步骤计算的,因此在进入迭代器之前,我真的不知道该长度。如果我不使用迭代器,则会耗尽内存-这是一个专业的解决方案。但是,是的,它只是我需要在常量代码的其余部分中使用的列表之一的长度。
答案 0 :(得分:2)
这就是迭代器的工作方式。但是除了T恤之外,您还有其他选择。
您可以提取第一个元素并在第二次迭代时重新使用它:
first_elem = next(my_iter)
list_len = len(first_elem)
for l in itertools.chain([first_elem], my_iter):
pass
或者如果您要遍历迭代器更多次,则可以列出它(如果可行的话,可以放入内存中)。
my_list = list(my_iter)
first_len = len(my_list[0])
for l in my_list:
pass
当然,正如Palivek所说的那样,从其他地方保存/获取有关列表长度的信息。
答案 1 :(得分:0)
通常,迭代器不可重复迭代,因此您可能仍然需要存储一些其他内容。
class peek_iterator(object):
def __init__(self, source):
self._source = iter(source)
self._first = None
self._sent = False
def __iter__(self):
return self
def next(self):
if self._first is None:
self._first = self._source.next()
if self._sent:
return self._source.next()
self._sent = True
return self._first
def get_isotropic(self, getter):
if self._first is None:
self._first = self._source.next()
return getter(self._first)
lists = [[1, 2, 3], [4, 5, 6]]
i = peek_iterator(lists)
print i.get_isotropic(len) # 3
for j in i: print j # [1, 2, 3]; [4, 5, 6]
答案 2 :(得分:0)
您可以做一些技巧,将原始迭代器包装在生成器中。这样,您可以获取第一个元素并使用生成器“重新屈服”它,而无需消耗整个迭代器。下面的head()
函数返回第一个元素和一个在原始序列上进行迭代的生成器。
def head(seq):
seq_iter = iter(seq)
first = next(seq_iter)
def gen():
yield first
yield from seq_iter
return first, gen()
seq = range(100, 300, 50)
first, seq2 = head(seq)
print('first item: {}'.format(first))
for item in seq2:
print(item)
输出:
first item: 100
100
100
150
200
250
从概念上讲,它等效于Moberg's answer,但是使用生成器而不是itertools.chain()
来“重新组合”原始序列。