从字典中查找相对数量

时间:2013-06-18 14:14:12

标签: python dictionary

我写了一个逻辑来查找位置的可用数量, 用字典管理位置和数量:

d={'loc2': 500.0, 'loc3': 200.0, 'loc1': 1000.0, 'loc4': 100.0, 'loc5': 50.0}

from operator import itemgetter
def find_combination(locs,qty):
    locs = sorted(locs.items(),key=itemgetter(1),reverse=True)
    result = []
    for loc,val in locs:
        if qty <= 0:
            break
        elif qty - val >= 0:
            qty -= val
            result.append((loc,val))
    return result

现在当数量低于dict中的最大数量时,它会给出这些意想不到的结果:

print find_combination(d,1000)
[('loc1', 1000.0)]
print find_combination(d,750)
[('loc2', 500.0), ('loc3', 200.0), ('loc5', 50.0)]
print find_combination(d,1900)
[('loc1', 1000.0), ('loc2', 500.0), ('loc3', 200.0), ('loc4', 100.0), ('loc5', 50.0)] 
print find_combination(d,150)
[('loc4', 100.0), ('loc5', 50.0)]
print find_combination(d,34)
[] # unexpected  # should be [('loc5', 50.0)]
print find_combination(d,88)
[('loc5', 50.0)] # should be [('loc4', 100.0)]

3 个答案:

答案 0 :(得分:2)

我不确定你的算法是否是你需要的算法。如果想要从不同的位置获得一定的数量,那么你的算法将找不到最佳组合,只是一个好的组合。

您的问题可以被视为0-1 knapsack problem,可以使用Dynamic Programming

在伪多项式时间内解决

答案 1 :(得分:1)

您只需使用dictionray键创建一个存储所有可能组合的字典,这将给出:

d={'loc2': 500.0, 'loc3': 200.0, 'loc1': 1000.0, 'loc4': 100.0, 'loc5': 50.0}
from itertools import combinations
comb = {}
for i in range(1,len(d)):
    [comb.__setitem__(sum(j),k) for k,j in zip(combinations(d.keys()  ,i),
                                               combinations(d.values(),i))]

comb字典如下:

{50.0: ('loc5',),
 100.0: ('loc4',),
 150.0: ('loc4', 'loc5'),
 200.0: ('loc3',),
 250.0: ('loc3', 'loc5'),
 300.0: ('loc3', 'loc4'),
 350.0: ('loc3', 'loc4', 'loc5'),
 500.0: ('loc2',),
 550.0: ('loc2', 'loc5'),
 600.0: ('loc2', 'loc4'),
 650.0: ('loc2', 'loc4', 'loc5'),
 700.0: ('loc2', 'loc3'),
 750.0: ('loc2', 'loc3', 'loc5'),
 800.0: ('loc2', 'loc3', 'loc4'),
 850.0: ('loc2', 'loc3', 'loc4', 'loc5'),
 1000.0: ('loc1',),
 1050.0: ('loc1', 'loc5'),
 1100.0: ('loc1', 'loc4'),
 1150.0: ('loc1', 'loc4', 'loc5'),
 1200.0: ('loc3', 'loc1'),
 1250.0: ('loc3', 'loc1', 'loc5'),
 1300.0: ('loc3', 'loc1', 'loc4'),
 1350.0: ('loc3', 'loc1', 'loc4', 'loc5'),
 1500.0: ('loc2', 'loc1'),
 1550.0: ('loc2', 'loc1', 'loc5'),
 1600.0: ('loc2', 'loc1', 'loc4'),
 1650.0: ('loc2', 'loc1', 'loc4', 'loc5'),
 1700.0: ('loc2', 'loc3', 'loc1'),
 1750.0: ('loc2', 'loc3', 'loc1', 'loc5'),
 1800.0: ('loc2', 'loc3', 'loc1', 'loc4')}

然后,如果给定的组合存在,您可以构建一个chekc函数:

 find_combination = lambda num: comb.get(num, 'NOT A VALID COMBINATION')

示例:

 find_combination(1750)
 #('loc2', 'loc3', 'loc1', 'loc5')

 find_combination(1):
 #'NOT A VALID COMBINATION'

编辑:如果你的字典太大,最好根据迭代器使用这个函数:

def find_combination(d, num):
    from itertools import combinations,izip
    t = ((sum(j),k) for i in range(1,len(d)) \
                    for j,k in izip(combinations(d.values(),i),
                                    combinations(d.keys()  ,i)))
    for comb,k in t:
        if comb==num: return k

答案 2 :(得分:0)

这是一个意想不到的结果?

qty = 34val = 50qty - val >= 0评估为假时。

qty = 88val = 100

的情况类似

你的程序结果对我来说听起来不错:)

旁注:

def find_combination(locs,qty):
  locs = sorted(d.items(),key=itemgetter(1),reverse=True)

但我想你的意思是locs = sorted(locs.items(), ...