在Python中找到一个列表的子集和

12

这可能很简单,我可能忽略了某些东西...

我有一个长整数列表,在这种情况下,它代表了网站的每日访问者。 我想要一个新的每周访客列表。 所以我需要从原始列表中获取七个元素组成一组,对其求和,并将结果添加到一个新列表中。

我的解决方案似乎相当暴力,不太优雅:

numweeks = len(daily) / 7
weekly = []
for x in range(numweeks):
    y = x*7
    weekly.append(sum(visitors[y:y+7]))

有没有更高效或更符合Python风格的方法可以做到这一点?


2
这实际上是一个很好的问题,可以在codereview.stackexchange.com上提出,该网站专门用于改进代码以使其更快/更优雅。 - Winston Ewert
谢谢...之前不知道那个StackExchange网站。如今有这么多问答平台,很难知道哪一个适合哪些问题。而且,这个似乎是最受关注的,所以我总觉得原始的回答最好。 :) - fitzgeraldsteele
这段代码没问题 - 它很简单并且清晰地传达了意图。我只会将变量名更改为比 xy 更具描述性的名称,但除此之外,这比任何基于理解的黑科技都更可取。 - Eli Bendersky
1
区别在于,那里你特别吸引那些喜欢阅读他人代码以找出更好方法的人的注意力。 - Winston Ewert
3个回答

15
weekly = [ sum(visitors[x:x+7]) for x in range(0, len(daily), 7)]

或稍微稀疏一些:

weekly = []
for x in range(0, len(daily), 7):
     weekly.append( sum(visitors[x:x+7]) )

或者,使用numpy模块。

by_week = numpy.reshape(visitors, (7, -1))
weekly = numpy.sum( by_week, axis = 1)

请注意,这需要visitor中元素的数量是7的倍数。还需要安装numpy。但这种方法可能比其他方法更有效率。

或者对于itertools代码奖励:

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)

weekly = map(sum, grouper(7, visitors, 0))

+1 包括 itertools.izip_longest 的情况,我希望你没有这样做,这样我就可以提到它。 :-) - Martijn Pieters
此外,对于大量访问者或如果访问者是一个生成器,itertools.izip_longest 和 itertools.imap选项更加高效,并且我会在第一个示例中使用xrange而不是range调用。 - Martijn Pieters

0
>>> daily = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
>>> print [sum(daily[x:x+7]) for x in range(0, len(daily), 7)]
[28, 77, 105]

我不确定这是否符合“Pythonic”的风格,但我真的很喜欢 Python 的一行代码。

详见:理解生成器表达式


0

使用 itertools.islice:

weekly = [sum(list(itertools.islice(daily, i, i+7)))
          for i in range(0, len(daily), 7)]

编辑:

或者,使用 math.fsum:

weekly = [math.fsum(itertools.islice(daily, i, i+7))
          for i in range(0, len(daily), 7)]

使用islice这样的方式并不是很高效。这样做会重复迭代daily中的元素。 - Winston Ewert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接