可拆分累加器与输出值的Scan算法:实现方案及技术问询
拆分整数列表为和不超过10的子列表:带分离累加器与输出的Scan算法需求
编辑说明:我询问的函数是mapAccumL
问题描述
拆分整数列表,使每个子列表的和不超过10
Python实现方案
以下是使用Python的itertools.accumulate(即scan)实现的逻辑:
import random import itertools # 生成示例列表 l = random.choices(range(5), k=30) # 示例列表:[2, 3, 3, 1, 4, 0, 3, 2, 0, 3, 3, 1, 2, 0, 2, 1, 2, 4, 4, 3, 1, 4, 2, 0, 3, 1, 4, 1, 0, 2] # 计算累加结果,当累加和超过等于10时重置为当前元素 scan_result = tuple(itertools.accumulate(l, lambda acc, x: x if acc + x >= 10 else acc + x)) # scan输出:(2, 5, 8, 9, 4, 4, 7, 9, 9, 3, 6, 7, 9, 9, 2, 3, 5, 9, 4, 7, 8, 4, 6, 6, 9, 1, 5, 6, 6, 8) # 定义相邻元素映射函数 adjacent_map = lambda fn, l: itertools.starmap(fn, zip(l, l[1:])) # 生成拆分掩码,相邻元素递减处标记为1 mask = (0,) + tuple(adjacent_map(lambda a, b: int(a > b), scan_result)) # 掩码输出:(0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0)
借助该掩码,可通过cut操作将原列表拆分为目标子列表:
# 最终拆分结果 [[2,3,3,1],[4,0,3,2,0],[3,3,1,2,0],[2,1,2,4],[4,3,1],[4,2,0,3],[1,4,1,0,2]]
也可在scan中一次性返回掩码,但此时lambda表达式会变得繁琐:
lambda acc, x: (x, 1, x) if acc[0] + x >= 10 else (acc[0] + x, 0, x)
这种实现方式关注点分离不佳,acc[0]仅用于scan的逻辑判断,后续无需使用,仅需acc[1:]。我需要一种scan算法,可拆分返回结果:result[0]作为下一次的累加器,result[1:]作为scan的输出值。
疑问
该问题是否已有解决方案或先例?Haskell中是否有相关实践?J或APL语言中是否有此类函数/运算符?
题外话:似乎需要自行编写库才能获得理想的解决方案。我使用C++编程,但不擅长自定义迭代器/范围。
内容的提问来源于stack exchange,提问作者Tom Huntington
相关产品推荐
相关产品推荐

