[英]Looking for the fastest way to divide dictionary keys (based on values) into lists of list such that each list does not cross a certain threshold
我有一个 OrderedDictionary a = {"1":800, "2":400, "3":600, "4":200, "5":100, "6":400}
我想将键分成列表列表,以便每个列表的总值不超过阈值(在本例中为 600),或者如果值大于阈值,它应该有自己的列表。 此外,我们只检查下一个键(如滑动窗口)。
上面的字典应该返回expected = [['1'], ['2'], ['3'], ['4', '5'], ['6']]
。 例如, '1'
有自己的列表,因为它大于阈值。 '2'
有自己的列表,因为'2' + '3'
的值大于阈值。 ['4', '5']
的值总计高达600
,如果我们 append '6'
,它超过了阈值。
这是我到目前为止所拥有的:
def check_result(a):
result = {}
curr_val = 0
threshold = 600
l =[]
result = []
for i in a.keys():
if curr_val >= threshold:
result.append(l)
l = []
curr_val = 0
if curr_val + a[i] > threshold:
result.append(l)
l = [i]
curr_val = a[i]
else:
l.append(i)
curr_val += a[i]
result.append(l)
print(result)
它将 output 作为[[], ['1'], ['2'], ['3'], ['4', '5'], ['6']]
给出。
在 O(n) 时间内寻找正确的解决方案。
谢谢!
第二个if
应该额外检查l
是否为空:
if curr_val + a[i] > threshold and l:
稍微不那么繁琐的代码:-
a = {"1": 800, "2": 400, "3": 600, "4": 200, "5": 100, "6": 400}
def check_result(d):
T = 600
result, e = [], []
s = 0
for k, v in d.items():
if e:
if s + v > T:
result.append(e)
else:
e.append(k)
s += v
continue
e = [k]
s = v
if e:
result.append(e)
return result
print(check_result(a))
根据运行总和,您可以通过将列表切换到 append 键来简化代码,以在整个结果和它的最后一个子列表之间。
a = {"1":800, "2":400, "3":600, "4":200, "5":100, "6":400}
t = 600 # Treshold
r = [] # result, list of lists of keys
s = 0 # running sum
for k,v in a.items():
group,item,delta = (r[-1],k,v) if r and s+v<=t else (r,[k],v-s)
group.append(item) # append to result or last sublist
s += delta # update running sum
print(r)
[['1'], ['2'], ['3'], ['4', '5'], ['6']]
或者这个更短(但效率较低)的变体:
r,s = [],0 # result, running sum
for k,v in a.items():
r += [r.pop(-1)+[k] if r and s+v<=t else [k]]
s += v - s*(s+v>t)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.