我有两个列表,如下
a = [646, 650, 654, 658, 662, 666, 670, 674, 678, 682, 686, 690, 694, 698, 702, 706, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593, 13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633, 13637, 13641, 13645, 13649, 13653, 13657, 13661, 21237, 21241, 21245, 21249, 21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289, 21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329, 21333, 21337, 21341, 21345]
b = [646, 706, 13661, 21345]
所以基本上我想根据列表 b
中的开始停止值将列表 a
分成更小的 block 。例如。
像这样的事情
[
[646, 650, 654, 658, 662, 666, 670, 674, 678, 682, 686, 690, 694, 698, 702, 706],
[13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593, 13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633, 13637, 13641, 13645, 13649, 13653, 13657, 13661],
[21237, 21241, 21245, 21249, 21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289, 21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329, 21333, 21337, 21341, 21345]
]
有人可以帮我解决这个问题吗?
最佳答案
解决方案1:使用二等分
我会使用 bisect
来解决这个问题模块查找 a
中每个项目的位置将被插入 b
确定某个项目属于哪个垃圾箱。
此解决方案不需要 a
已排序,但它确实需要 b
已排序。
bin_boundaries = sorted(b)
results = [[] for _ in range(len(bin_boundaries)+1)]
for i in a:
pos = bisect.bisect_left(bin_boundaries, i)
results[pos].append(i)
print(results)
现在,您没有指定是否需要等于上一个或下一个垃圾箱中的边界的项目。我把它放在之前的垃圾箱里了。如果您指的是下一个,请替换 bisect_left
通过bisect_right
如上所述。
我还输出了您预期输出显示的另外两个垃圾箱:第一个垃圾箱的项目小于第一个垃圾箱边界,最后一个垃圾箱的项目大于最后一个边界。添加results = results[1:-1]
如果您想删除这些边缘垃圾箱。
解决方案 2:只需循环遍历每个 bin 的列表
现在,这是一个更简单的解决方案,只需遍历 a
对于每个垃圾箱:
bin_boundaries = sorted(b)
results = []
for low, high in zip(bin_boundaries[:-1], bin_boundaries[1:]):
results.append([i for i in a if i > low and i <= high])
print(results)
这一次,我没有创建边缘垃圾箱。再次修复 >
和<=
以匹配您在边缘实际想要的语义。
该外循环也可以转换为列表理解,为您提供嵌套列表理解和一个非常紧凑的解决方案:
results = [
[i for i in a if i > low and i <= high]
for low, high in zip(bin_boundaries[:-1], bin_boundaries[1:])
]
关于python - 根据另一个列表中的元素进行列表划分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70364690/