我有一个sumranges()函数,它对元组元组中找到的所有连续数字的范围求和.为了显示:
def sumranges(nums):
return sum([sum([1 for j in range(len(nums[i])) if
nums[i][j] == 0 or
nums[i][j - 1] + 1 != nums[i][j]]) for
i in range(len(nums))])
>>> nums = ((1, 2, 3, 4), (1, 5, 6), (19, 20, 24, 29, 400))
>>> print sumranges(nums)
7
Run Code Online (Sandbox Code Playgroud)
如您所见,它返回元组内连续数字的范围数,即:len((1,2,3,4),(1),(5,6),(19,20),( 24),(29),(400))= 7.元组总是有序的.
我的问题是我的sumranges()很糟糕.我讨厌看着它.我现在只是迭代元组和每个子元素,如果数字不是(1 +前一个数字),则分配1,并总计总和.我觉得我错过了一种更容易实现既定目标的方法.有没有人知道更多的pythonic方式来做到这一点?
编辑:我已经对迄今为止给出的所有答案进行了基准测试.感谢大家的回答.
基准测试代码如下,使用100K的样本大小:
from time import time
from random import randrange
nums = [sorted(list(set(randrange(1, 10) for i in range(10)))) for
j in range(100000)]
for func in sumranges, alex, matt, redglyph, ephemient, ferdinand:
start = time()
result = func(nums)
end = time()
print ', '.join([func.__name__, str(result), str(end - start) + ' s'])
Run Code Online (Sandbox Code Playgroud)
结果如下.显示的实际答案是为了验证所有函数是否返回正确的答案:
sumranges, 250281, 0.54171204567 s
alex, 250281, 0.531121015549 s
matt, 250281, 0.843333005905 s
redglyph, 250281, 0.366822004318 s
ephemient, 250281, 0.805964946747 s
ferdinand, 250281, 0.405596971512 s
Run Code Online (Sandbox Code Playgroud)
RedGlyph在速度方面确实优势,但最简单的答案可能是费迪南德,并且可能赢得大多数pythonic.
Fer*_*yer 14
我的2美分:
>>> sum(len(set(x - i for i, x in enumerate(t))) for t in nums)
7
Run Code Online (Sandbox Code Playgroud)
这与Alex的帖子中描述的基本相同,但使用a set而不是itertools.groupby,导致表达更短.由于sets是用C实现的,而len()一组是在恒定时间内运行的,所以这也应该非常快.
考虑:
>>> nums = ((1, 2, 3, 4), (1, 5, 6), (19, 20, 24, 29, 400))
>>> flat = [[(x - i) for i, x in enumerate(tu)] for tu in nums]
>>> print flat
[[1, 1, 1, 1], [1, 4, 4], [19, 19, 22, 26, 396]]
>>> import itertools
>>> print sum(1 for tu in flat for _ in itertools.groupby(tu))
7
>>>
Run Code Online (Sandbox Code Playgroud)
我们通过从该值中减去该指数来"平滑"所关注的"增加的斜率",将它们变成相同值的连续"运行"; 然后我们确定并且可以与珍贵的"奔跑" itertools.groupby.这似乎是一个非常优雅(和快速)解决您的问题的方法.
只是为了展示更接近原始代码的内容:
def sumranges(nums):
return sum( (1 for i in nums
for j, v in enumerate(i)
if j == 0 or v != i[j-1] + 1) )
Run Code Online (Sandbox Code Playgroud)
这里的想法是:
sum()尽管如此,剩下的仍然是必要的.