Python - 如何使用几次相同的下一次迭代?

Python - how to use few times the same next iteration?

我要搜索列表:

[0, 0, 1, 0, 1, 1, 1, 0, 1, 1] 

和replace/edit项不同于上一项和下一项。对于 xxample:我想删除上面列表中索引 2 处的 of/edit 1

看看我下面的代码,请继续阅读我的代码下面的核心问题:

!更新: 结果应该是:[0, 0, 0, 0, 1, 1, 1, 1, 1, 1]

x = [0, 0, 1, 0, 1, 1, 1, 0, 1, 1]
print(x)
hiter = iter(x)
next(hiter)
prev = None

for i in x:
    try:
        print('prev %s - CURRENT %s - next %s' % (prev, i, next(hiter)))
        prev = i

        #if i != prev and i != next(hiter):
        #   x[i] = prev 

    except StopIteration:
        break

print(x)

我们知道上一项、下一项和当前项目。

但每次我使用:

if i != prev and i != next(hiter)...

next(hiter) 破坏秩序。换句话说,如果我在循环中使用 next(hiter) 超过 1 次,Python 会将下一项读取为双精度,因为我在循环中使用了两次 next(hiter)。

我也试过像 y = next(hiter) 这样声明单独的变量 - 但它仍然没有用(显然不会用,但我还是很想检查它 xD)。

我没有线索,另外,hiter.__next__()next(hiter)一样。

你把事情搞得太复杂了。相反,只需在循环中多次阅读 x

for idx in range(1, len(x)-1): # Consider using enumerate, it's a great idea
    curr = x[idx]
    prev = x[idx - 1]
    nxt = x[idx + 1]
    if (curr != prev) and (curr != nxt):
        print('prev %s - CURRENT %s - next %s' % (prev, curr, nxt))

有一个 itertools.tee 函数允许 "clone" 个迭代器。

iter1, iter2 = itertools.tee(iter(<iterable>))

你的案例看起来太琐碎了 - 除非它只是例子,否则就使用它

编辑 那样的话

for index, val in enumerate(x[1:-1], 1)
    if val != x[index-1] and val != x[index+1]:
        x[index] = x[index-1]

您可以使用一个生成器来保留前一项并向前看一项:

def gen(x):
    x = iter(x)
    # Get the first item and simply yield it
    first = next(x)
    yield first

    # create a list containing the previous element, the current element and the next element
    # and iterate over your input.
    three = [None, first, next(x)]
    for item in x:
        # Update the list of elements: Remove the previous previous item and
        # add the new next item.
        three = three[1:] + [item]
        prev, cur, nxt = three

        if cur != prev and cur != nxt:
            three[1] = prev  # replace the current item with the previous item
            yield prev

        else:
            yield cur

    # Simply yield the last item
    yield three[-1]


>>> list(gen([0, 0, 1, 0, 1, 1, 1, 0, 1, 1]))
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1]

在这种方法中,我只是返回了第一项和最后一项而不进行检查,因为只有下一项或上一项,而不是两者。如果你愿意,你也可以在那里放一些支票。

正如@MadPhysicist 指出的那样,根本不需要列表,您可以简单地为 previouscurrentnext 项使用一个变量:

def gen(x):
    x = iter(x)
    # Get the first item and simply yield it
    first = next(x)
    yield first

    cur, nxt = first, next(x)  # Initial current and next item
    for item in x:
        prev, cur, nxt = cur, nxt, item  # Update the previous, current and next item

        if cur != prev and cur != nxt:
            cur = prev
            yield prev

        else:
            yield cur

    # Simply yield the last item
    yield nxt

注意:这两种方法都会创建一个新列表,不会修改原始列表。

您可能想通过索引访问您的列表元素。在您的循环中,您可以通过添加或减去当前索引来访问上一个和下一个项目。

请记住,在列表中,您可以使用 hiter[0]hiter[1]、...访问元素,并在循环中作为:

for i in range(len(hiter)-1):
    print("The item is %s" % hiter[i])

因此您可以访问上一个和下一个,只需要处理边缘情况(以防止索引超出范围)。一种方法是:

for i in range(len(hiter)):
    if 0 < i < (len(hiter) - 1):
        print("The items are %s, %s, %s" % (hiter[i-1], hiter[i], hiter[i+1]))
    elif i == 0:
        print("The items are %s, %s" % (hiter[i], hiter[i+1]))
    elif i == (len(hiter) - 1):
        print("The items are %s, %s" % (hiter[i-1], hiter[i]))

以同样的方式,您可以使用相同的索引方法更改可变列表中的值。

!更新 2: 感谢大家的贡献。这真的很有帮助,我今天学到了很多东西。这就是我的意思(抱歉@MSeifert,但我必须按照自己的方式去做,我知道生成器速度更快,而且它们不会占用内存)。
解决方案:

x = [0, 0, 1, 0, 1, 1, 1, 0, 1, 1]
print(x)
for i in range(1, len(x)-1):
    current = x[i]
    nxt = x[i+1]
    prev = x[i-1]

    if current != prev and current != nxt:
        print('prev: %s - CURRENT: %s - next: %s [ X ]' % (prev, current, nxt))
        x[i] = x[i-1]
    else:
        print('prev: %s - CURRENT: %s - next: %s' % (prev, current, nxt))

print(x)