我需要从一个线性整数列表(不能从0开始)中得到一个 "相等 "的步长,但有以下要求。
一些例子。
用一个列表从 range(10)
和第2步,结果应该是以下之一。
[0, 2, 5, 7, 9]
[0, 2, 4, 7, 9]
与 range(21)
和步骤3。
[0, 3, 7, 10, 14, 17, 20]
与 range(1, 22)
和第三步。
[1, 4, 8, 11, 15, 18, 21]
现在我得到了一些类似于这个的东西, 很明显它不能正常工作。
def getSlices(l, s):
skipCount = (len(l) - 1) % s
divCount = int(len(l) / (skipCount + 1))
o = []
for delta, skip in enumerate(range(skipCount + 1)):
o.extend(l[skip * divCount + delta:(skip + 1) * divCount + delta:s])
return o
>>> getSlices(list(range(21)), 3)
[0, 3, 6, 8, 11, 14, 16, 19]
我知道我可以循环浏览所有的值,通过关联跳过。enumerate
索引和步长,并在达到列表的新 "部分 "时立即添加一个 "delta",但这似乎不是性能最好的解决方案。
我想这可以按照你的要求去做。希望它能帮助你。
def getSlices(l, step):
init = l[0]
last = l[-1] # exclude last element (remove as you want)
slices = (last-init) // step + 1
mod = (last-init) % step
even = mod // 2
mid = slices // 2 - 1
even_start = mid - even
even_end = mid + mod - even
final = []
val = init
for i in range(slices):
final.append(val)
val += step
# Distribute mod unitary in the middle
if slices-1 >= mod:
if mod > 0 and (even_start <= i <= even_end):
val += 1
# In case is the middle don't change it
if i == mid:
val += - 1
# Distribute mod evenly all across the slices
else:
val += mod // (slices-1)
# In case a there is mod left, place it just in the middle
if i == mid:
val += mod % (slices-1)
return final
# Examples:
#
# getSlices(list(range(10)), 2)
# [0, 2, 4, 7, 9]
#
# getSlices(list(range(21)), 3)
# [0, 3, 7, 10, 14, 17, 20]
#
# getSlices(list(range(1, 22)), 3)
# [1, 4, 8, 11, 15, 18, 21]
#
# getSlices(list(range(36)), 10)
# [0, 11, 24, 35]