for x in records:
data = {}
for y in sObjectName.describe()['fields']
data[y['name']] = x[y['name']]
ls.append(adapter.insert_posts(collection, data))
我想执行批量大小为500的代码ls.append(adapter.insert_post(collection,x)),其中x应包含500个数据dicts。我可以使用double for循环和列表创建500个数据dicts的列表,然后插入它。我可以通过以下方式做到这一点,有没有更好的方法呢? :
for x in records:
for i in xrange(0,len(records)/500):
for j in xrange(0,500):
l=[]
data = {}
for y in sObjectName.describe()['fields']:
data[y['name']] = x[y['name']]
#print data
#print data
l.append(data)
ls.append(adapter.insert_posts(collection, data))
for i in xrange(0,len(records)%500):
l=[]
data = {}
for y in sObjectName.describe()['fields']:
data[y['name']] = x[y['name']]
#print data
#print data
l.append(data)
ls.append(adapter.insert_posts(collection, data))
答案 0 :(得分:24)
我使用的一般结构如下:
worklist = [...]
batchsize = 500
for i in xrange(0, len(worklist), batchsize):
batch = worklist[i:i+batchsize] # the result might be shorter than batchsize at the end
# do stuff with batch
请注意,我们正在使用step
的{{1}}参数来大大简化批处理。
答案 1 :(得分:7)
如果你正在处理序列,那么@nneonneo的解决方案就像你能得到的那样高效。如果你想要一个适用于任意迭代的解决方案,你可以查看一些itertools recipes。例如石斑鱼:
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return itertools.izip_longest(fillvalue=fillvalue, *args)
我倾向于不使用这个,因为它用None
“填充”最后一个组,因此它与其他组的长度相同。我通常定义我自己的变体,它没有这种行为:
def grouper2(iterable, n):
iterable = iter(iterable)
while True:
tup = tuple(itertools.islice(iterable, 0, n))
if tup:
yield tup
else:
break
这会产生所请求大小的元组。这通常是足够好的,但是,为了一点乐趣,我们可以编写一个生成器,如果我们真的想要...返回正确大小的惰性迭代...
我认为这里的“最佳”解决方案取决于手头的问题 - 特别是原始可迭代中的组和对象的大小以及原始可迭代的类型。一般来说,最后2个食谱的用量较少,因为它们更复杂,很少需要。但是,如果您喜欢冒险并且心情愉快,请继续阅读!
我们需要获得一个惰性迭代而不是元组的唯一真正修改是能够“查看”islice
中的下一个值以查看是否有任何内容。在这里我只是看看价值 - 如果它丢失了,StopIteration
将被提升,这将停止发电机,就像它正常结束一样。如果它在那里,我用itertools.chain
:
def grouper3(iterable, n):
iterable = iter(iterable)
while True:
group = itertools.islice(iterable, n)
item = next(group) # raises StopIteration if the group doesn't yield anything
yield itertools.chain((item,), group)
小心,但是如果你完全耗尽每个迭代,那么只有“才能工作”继续移动到下一个。在极端情况下,您不会耗尽任何迭代,例如, list(grouper3(..., n))
,你将得到“m”个迭代,它只产生1个项目,而不是n
(其中“m”是输入可迭代的“长度”)。这种行为有时可能很有用,但通常不常见。如果我们使用itertools“consume”配方(除collections
之外还需要导入itertools
),我们也可以解决这个问题:
def grouper4(iterable, n):
iterable = iter(iterable)
group = []
while True:
collections.deque(group, maxlen=0) # consume all of the last group
group = itertools.islice(iterable, n)
item = next(group) # raises StopIteration if the group doesn't yield anything
group = itertools.chain((item,), group)
yield group
当然,list(grouper4(..., n))
将返回空的迭代 - 在next
的下一次调用之前未从“组”中提取的任何值(例如,当for
循环循环回到开始)永远不会屈服。
答案 2 :(得分:1)
也许是这样的?
l = []
for ii, x in enumerate(records):
data = {}
for y in sObjectName.describe()['fields']
data[y['name']] = x[y['name']]
l.append(data)
if not ii % 500:
ls.append(adapter.insert_posts(collection, l))
l = []
答案 3 :(得分:1)
我认为这里不涉及一种特殊情况。假设批次大小为100,列表大小为103,以上答案可能会漏掉最后3个元素。
list = [.....] 103 elements
total_size = len(list)
batch_size_count=100
for start_index in range(0, total_size, batch_size_count):
end_index = total_size if start_index + batch_size_count > total_size else start_index + batch_size_count
list[start_index:end_index] #Slicing operation
可以将切片列表发送给每个方法调用,以完成所有元素的执行。