Python“Every Other Element”成语

时间:2010-04-13 16:11:52

标签: python idioms

我觉得我花了很多时间在Python中编写代码,但没有足够的时间创建Pythonic代码。最近我遇到了一个有趣的小问题,我认为可能有一个简单,惯用的解决方案。解释原文,我需要收集列表中的每个连续对。例如,给定列表[1,2,3,4,5,6],我想计算[(1,2),(3,4),(5,6)]

我想出了一个看起来像翻译Java的快速解决方案。重新审视这个问题,我能做的最好的就是

l = [1,2,3,4,5,6]
[(l[2*x],l[2*x+1]) for x in range(len(l)/2)]

,如果长度不均匀,会产生抛弃最后一个数字的副作用。

我是否缺少一种更为惯用的方法,或者这是我最好的方法?

8 个答案:

答案 0 :(得分:82)

这样做会更加整洁:

>>> data = [1,2,3,4,5,6]
>>> zip(data[0::2], data[1::2])
[(1, 2), (3, 4), (5, 6)]

(但如果你不熟悉范围的“跨步”特征,它可以说是不太可读。)

与您的代码一样,它会丢弃您具有奇数个值的最后一个值。

答案 1 :(得分:49)

经常被引用的是:

zip(*[iter(l)] * 2)

我更喜欢iter解决方案的这个更易阅读的版本:

it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]

答案 2 :(得分:9)

我通常会将grouper文档中的def grouper(n, iterable, fillvalue=None): "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" args = [iter(iterable)] * n return izip_longest(fillvalue=fillvalue, *args) 食谱复制到我的代码中。

{{1}}

答案 3 :(得分:8)

如何使用range()的步骤功能:

[(l[n],l[n+1]) for n in range(0,len(l),2)]

答案 4 :(得分:4)

试试这个

def pairs(l, n):
    return zip(*[l[i::n] for i in range(n)])

所以,

pairs([1, 2, 3, 4], 2) 给出

[(1, 2), (3, 4)]

答案 5 :(得分:4)

正确的事情可能不是计算列表,而是编写迭代器 - >迭代器函数。这是更通用的 - 它适用于每个可迭代的,如果你想将它“冻结”到一个列表中,你可以使用“list()”函数。

def groupElements(iterable, n):
    # For your case, you can hardcode n=2, but I wanted the general case here.
    # Also, you do not specify what to do if the 
    # length of the list is not divisible by 2
    # I chose here to drop such elements
    source = iter(iterable)
    while True:
        l = []
        for i in range(n):
            l.append(source.next())
        yield tuple(l)

我很惊讶itertools模块还没有这方面的功能 - 也许是未来的修订版。在此之前,请随意使用上面的版本:)

答案 6 :(得分:4)

toolz是一个精心构建的库,在itertools中忽略了许多函数式编程细节。 partition解决了这个问题(可以选择填充奇数长度列表的最后一个条目)

>>> list(toolz.partition(2, [1,2,3,4,5,6]))
[(1, 2), (3, 4), (5, 6)]

答案 7 :(得分:3)

如果您不希望丢失元素,如果列表中的数字不是,请尝试:

>>> l = [1, 2, 3, 4, 5]
>>> [(l[i],  l[i+1] if i+1 < len(l) else None)  for i in range(0, len(l), 2)]
[(1, 2), (3, 4), (5, None)]