本问题已经有最佳答案,请猛点这里访问。
我觉得我花了很多时间在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)]
在长度不均匀的情况下,其具有抛弃最后一个数字的副作用。
是否有一种我不知道的惯用方法,或者这是我最好的方法?
相关的"什么是最"pythonic"以块的形式迭代列表?"stackoverflow.com/questions/434287/
这样做会更整齐:
>>> data = [1,2,3,4,5,6]
>>> zip(data[0::2], data[1::2])
[(1, 2), (3, 4), (5, 6)]
(但如果你不熟悉范围的"跨步"特征,它可以说可读性较差)。
与您的代码一样,它会丢弃您具有奇数个值的最后一个值。
在执行上述操作之前,您可以执行data += [None]来处理奇数项目方案。
some_list += [foo]写为some_list.append(foo)。
这次迭代数据多少次?看看这个答案
经常被引用的是:
zip(*[iter(l)] * 2)
我更喜欢iter解决方案的更易读的版本:
it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
太棒了,但读起来像perl ;-)
没错,但我认为这也是迄今为止提出的最有效的解决方案。我会测试,brb。
是的,它比RichieHindle的解决方案快10%左右,因为它不需要任何内存分配,只需要在输入列表上进行一次迭代。
+1因为我以前从未知道*解包参数列表!
这是一种灵活的方法,但显然不太可读,特别是对于不太高级的Python开发人员。这就是为什么我喜欢用grouper来抽象它的作用。
知道,虽然RichieHindle赢得了接受的答案(真的很难忽视可读性),但这个答案赢得了我的心。
值得注意的是,这直接来自Python文档。
我通常将itertools文档中的grouper配方复制到我的代码中。
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
如何使用range()的步骤功能:
[(l[n],l[n+1]) for n in range(0,len(l),2)]
toolz是一个精心构建的库,在itertools中忽略了许多功能编程细节。 partition解决了这个问题(可以选择填充奇数长度列表的最后一个条目)
>>> list(toolz.partition(2, [1,2,3,4,5,6]))
[(1, 2), (3, 4), (5, 6)]
正确的事情可能不是计算列表,而是编写迭代器 - >迭代器函数。这是更通用的 - 它适用于每个可迭代的,如果你想将它"冻结"到一个列表中,你可以使用"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模块还没有这个功能 - 也许是未来的版本。在此之前,随意使用上面的版本:)
这与性能有什么关系?
试试这个
def pairs(l, n):
return zip(*[l[i::n] for i in range(n)])
所以,
pairs([1, 2, 3, 4], 2)
给
[(1, 2), (3, 4)]
如果您不希望丢失元素,如果列表中的数字不是,请尝试这样:
>>> 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)]