作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
给定一条 python list
的 bytes
值(value)观:
# actual str values un-important
[
b'foo',
b'bar',
b'baz',
...
]
[
[b'foo', b'bar'], # sublist 0
[b'baz'], # sublist 1
...
]
最佳答案
可以贪婪地解决序列的最优拆分问题,以使元素满足给定的最大/最小条件同时保持元素的顺序。
因此,您只需对输入序列进行一次迭代并维护一个元素缓冲区。
在 Python 中,这可以用生成器优雅地编码,这将具有不需要创建结果的优点。
您的问题的大部分算法如下:
def split_by_size(items, max_size, get_size=len):
buffer = []
buffer_size = 0
for item in items:
item_size = get_size(item)
if buffer_size + item_size <= max_size:
buffer.append(item)
buffer_size += item_size
else:
yield buffer
buffer = [item]
buffer_size = item_size
if buffer_size > 0:
yield buffer
len()
会做。
import random
k = 10
n = 15
max_size = 10
random.seed(0)
items = [b'x' * random.randint(1, 2 * k // 3) for _ in range(n)]
print(items)
# [b'xxxx', b'xxxx', b'x', b'xxx', b'xxxxx', b'xxxx', b'xxxx', b'xxx', b'xxxx', b'xxx', b'xxxxx', b'xx', b'xxxxx', b'xx', b'xxx']
print(list(split_by_size(items, k)))
# [[b'xxxx', b'xxxx', b'x'], [b'xxx', b'xxxxx'], [b'xxxx', b'xxxx'], [b'xxx', b'xxxx', b'xxx'], [b'xxxxx', b'xx'], [b'xxxxx', b'xx', b'xxx']]
list
无论如何,上述方法的代码可以稍微紧凑一些:
def chunks_by_size(items, max_size, get_size=len):
result = []
size = max_size + 1
for item in items:
item_size = get_size(item)
size += item_size
if size > max_size:
result.append([])
size = item_size
result[-1].append(item)
return result
functools.reduce()
(与
@NizamMohamed answer 基本相同),代码会更短,但也可能更不可读:
def chunks_by_size_reduce(items, size, get_size=len):
return functools.reduce(
lambda a, b, size=size:
a[-1].append(b) or a
if a and sum(get_size(x) for x in a[-1]) + get_size(b) <= size
else a.append([b]) or a, items, [])
get_size()
正在为所考虑的每个元素的“候选”内部列表的每个元素调用,这使得
O(n k!)
,
k
是每个子序列中元素的平均数量。对于某些时间,请参阅下面的基准。
itertools.accumulate()
的解决方案感到惊讶,但这也必然会很慢。
split_by_size()
.
_cy
代表 Cython 编译的版本,而
_nb
代表 Numba 编译的版本):
%timeit list(split_by_size(items * 100000, k + 1))
# 10 loops, best of 3: 281 ms per loop
%timeit list(split_by_size_cy(items * 100000, k + 1))
# 10 loops, best of 3: 181 ms per loop
%timeit list(split_by_size_nb(items * 100000, k + 1))
# 100 loops, best of 3: 5.17 ms per loop
%timeit chunks_by_size(items * 100000, k + 1)
# 10 loops, best of 3: 318 ms per loop
%timeit chunks_by_size_reduce(items * 100000, k + 1)
# 1 loop, best of 3: 1.18 s per loop
forceobj
标志设置为
True
,这可能会导致执行不稳定。
关于python - 将 Python 列表拆分为具有最大内存大小的 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60960535/
我是一名优秀的程序员,十分优秀!