繁体   English   中英

Python循环:以惯用方式比较列表中的连续项

[英]Python looping: idiomatically comparing successive items in a list

我需要循环一个对象列表,比较它们是这样的:0对1,1对2,2对3等等(我正在使用pysvn来提取差异列表。)我结束了循环索引,但我一直想知道是否有某种方法可以做到更贴近惯用。 这是Python; 我不应该以某种聪明的方式使用迭代器吗? 简单地循环索引似乎很清楚,但我想知道是否有更具表现力或简洁的方法来做到这一点。

for revindex in xrange(len(dm_revisions) - 1):
    summary = \
        svn.diff_summarize(svn_path,
                          revision1=dm_revisions[revindex],
                          revision2 = dm_revisions[revindex+1])

这称为滑动窗口。 itertools文档中有一个例子可以做到这一点。 这是代码:

from itertools import islice

def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result    
    for elem in it:
        result = result[1:] + (elem,)
        yield result

那是什么,你可以这样说:

for r1, r2 in window(dm_revisions):
    summary = svn.diff_summarize(svn_path, revision1=r1, revision2=r2)

当然你只关心n = 2的情况,所以你可以更简单地得到一些东西:

def adjacent_pairs(seq):
    it = iter(seq)
    a = it.next()
    for b in it:
        yield a, b
        a = b

for r1, r2 in adjacent_pairs(dm_revisions):
    summary = svn.diff_summarize(svn_path, revision1=r1, revision2=r2)

我可能会这样做:

import itertools
for rev1, rev2 in zip(dm_revisions, itertools.islice(dm_revisions, 1, None)):
    summary = svn.diff_sumeraize(svn_python, revision1=rev, revision2=rev2)

类似地更聪明并且不接触迭代器本身的东西可能可以使用

发布了如此多的复杂解决方案,为什么不保持简单?

myList = range(5)

for idx, item1 in enumerate(myList[:-1]):
    item2 = L[idx + 1]
    print item1, item2

>>> 
0 1
1 2
2 3
3 4

将先前的值存储在变量中。 使用您在处理的序列中找不到的值初始化变量,这样您就可以知道您是否处于第一个元素。 将旧值与当前值进行比较。

如果您注意在还原功能的结果中保留当前项目的副本 ,则可以将Reduce用于此目的。

def diff_summarize(revisionList, nextRevision):
    '''helper function (adaptor) for using svn.diff_summarize with reduce'''
    if revisionList:
        # remove the previously tacked on item
        r1 = revisionList.pop()
        revisionList.append(svn.diff_summarize(
            svn_path, revision1=r1, revision2=nextRevision))
    # tack the current item onto the end of the list for use in next iteration
    revisionList.append(nextRevision)
    return revisionList

summaries = reduce(diff_summarize, dm_revisions, [])

编辑:是的,但没有人说reduce函数的结果必须是标量。 我改变了我的例子以使用列表。 基本上,最后一个元素是前一个修订版(第一遍除外),所有前面的元素都是svn.diff_summarize调用的结果。 这样,您可以获得结果列表作为最终输出...

EDIT2:是的 ,代码真的坏了。 我这里有一个可行的假人:

>>> def compare(lst, nxt):
...    if lst:
...       prev = lst.pop()
...       lst.append((prev, nxt))
...    lst.append(nxt)
...    return lst
...
>>> reduce(compare, "abcdefg", [])
[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e'), ('e', 'f'), ('f', 'g'), 'g']

正如您所看到的,这在shell中进行了测试。 您将需要在comparelst.append调用中替换(prev, nxt)以实际将调用的摘要附加到svn.diff_summarize

>>> help(reduce)
Help on built-in function reduce in module __builtin__:

reduce(...)
    reduce(function, sequence[, initial]) -> value

    Apply a function of two arguments cumulatively to the items of a sequence,
    from left to right, so as to reduce the sequence to a single value.
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
    ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
    of the sequence in the calculation, and serves as a default when the
    sequence is empty.

暂无
暂无

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

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