简体   繁体   English

比较列表中所有相邻元素的Pythonic方法

[英]Pythonic way of comparing all adjacent elements in a list

I want to know if there's a more Pythonic way of doing the following: 我想知道是否有更多的Pythonic方法来执行以下操作:

A = some list
i = 0
j = 1
for _ in range(1, len(A)):
    #some operation between A[i] and A[j]
    i += 1
    j += 1

I feel like this should/could be done differently. 我觉得这应该/可以做得不同。 Ideas? 想法?

EDIT: Since some are asking for requirements. 编辑:因为有些人要求要求。 I wanted a general-purpose answer. 我想要一个通用的答案。 Maybe to check if A[i], A[j] are between a certain range, or if they're equal. 也许检查A [i],A [j]是否在某个范围之间,或者它们是否相等。 Or maybe I wanted to do a "trickle-up" of elements. 或许我想做一个“涓涓细流”的元素。 The more general, the better. 越普遍越好。

There's a nice little recipe in itertools for doing this. 为了做到这一点,在itertools有一个很好的小方法。 As a bonus it works with any iterable, not just sequences. 作为奖励,它适用于任何可迭代的,而不仅仅是序列。

from itertools import tee

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

for current, next_ in pairwise(A):
    # do something
    pass

If you need the index as well then just enumerate the pairwise iterator. 如果您还需要索引,那么只需enumerate成对迭代器。

for current_index, (current, next_) in enumerate(pairwise(A)):
    # do something
    pass

For operation '+': 对于'+'操作:

A = [A[i+1]+A[i] for i in range(len(A)-1)]

General: 一般:

A = [operation(A[i], A[i+1]) for i in range(len(A)-1)]

zip lets you combine multiple iterators: zip允许您组合多个迭代器:

for i,j in zip(range(0,len(A)-1), range(1,len(A))):
    #some operation between A[i] and A[j]

you can also use enumerate on a range object: 你也可以在范围对象上使用enumerate

for i,j in enumerate(range(1,len(A)):
    #some operation between A[i] and A[j]

Note that unlike the other answers this gives you access to the indices of A not just the items, this is necessary if you want to use any assignment to A[i] or A[j] , for example here is a very basic bubble sort: 请注意,与其他答案不同,这使您可以访问A的索引而不仅仅是项目,如果您想对A[i]A[j]使用任何赋值 ,这是必要的,例如这里是一个非常基本的冒泡排序:

A = list(range(10))
found1=True
while found1:
    found1=False
    for i,j in enumerate(range(1,len(A))):
        if A[i] < A[j]:
            A[i],A[j] = A[j],A[i]
            found1=True
print(A)

this is only possible when you iterate over the indices of A. 只有在迭代A的索引才有可能。

You could do : 你可以这样做:

A = some list
for Ai, Aj in zip(A, A[1:]):
    #some operation between A[i] and A[j]
from itertools import islice
A1 = iter(A)
A2 = islice(A, 1, None)
for a1, a2 in zip(A1, A2):
    # do whatever with A[i], A[i+1]

islice is more generic than using A[1:] since it works on iterators (which are not subscriptable) as well. islice比使用A[1:]更通用,因为它也适用于迭代器(也不是可订阅的)。 Please note that you need to pass None as the third parameter because islice(iterable, stop) only returns the first stop items of the iterator (hence the name) which is exactly the opposite of what you want, when a third parameter is passed it treats the second as starting position rather than stopping index. 请注意,您需要传递None作为第三个参数,因为islice(iterable, stop)只返回迭代器的第一个stop项(因此名称),当第三个参数传递给它时,它与您想要的完全相反将第二个视为起始位置而不是停止索引。

islice(iterable, start, stop[, step])  # roughly = iterable[start:stop:step]
islice(iterable, stop)                 # roughly = iterable[:stop]

Please refer to the docs for more info. 有关详细信息,请参阅文档

Now zip() emits values till the shortest iterator( A2 ) is exhausted. 现在zip()发出值,直到shortest迭代器( A2 )耗尽。 So no worries about the possible IndexError . 所以不用担心可能的IndexError

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM