python - 通过保持最小值和最大值对列表进行等步切片
问题描述
我需要从一个线性整数列表(不能从 0 开始)中获得一个“相等”的步长切片,但有以下要求:
- 最后一个值(最大值)总是必须出现
- 不能有低于步长的间隔(最重要的是,在倒数第二个值和最后一个值之间)
- 鉴于以上几点,某些间隔可能高于步长,并且这些间隔必须平均放置在结果列表之间
- 只应使用标准库函数(无 numpy)
一些例子:
使用来自
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)
第3步:[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
索引和步骤跳过,并在到达列表的新“部分”时添加一个“增量”,但这似乎不是最有效的解决方案。
解决方案
我认为这可能会如你所愿。希望能帮助到你。
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]
推荐阅读
- java - @ConfigurationProperties 在以编程方式添加活动配置文件后重新加载
- python - 最喜欢的运动有两个列表。一个是自动化的,一个是用户输入的。找到交叉点
- c++ - Google 测试发现在 mac OS X 上添加并运行了我所有的测试两次
- sas - 通过 & 使用 symget 与取消引用
- python - Django 隐式更新所有字段
- excel - 如何在excel中转置不同的列?
- express - aws sns 确认订阅请求处理问题
- apache-spark - Spark Dataframe 中的过滤操作
- json - json格式不美化json
- python - Django启动时如何输入字符串?