在词典中找到最适合约束的下一个键

时间:2016-11-13 03:18:51

标签: python algorithm list dictionary greedy

我有一个名字的字典:牛的重量。

cows = {'Herman': 7, 'Moo Moo': 3, 'Betsy': 9, 'Lola': 2, 'Milkshake': 2, 'Florence': 2, 'Henrietta': 9, 'Maggie': 3, 'Millie': 5, 'Oreo': 6}

我必须使用贪心算法从这本词典中创建一个列表列表。每个子列表都有一个约束:权重限制为10.这意味着,我必须先按重量选择最大的牛,然后找到适合子列表的下一头牛。例如,这个字典问题的正确答案是:

[ ['Betsy'],
['Henrietta'],
['Herman', 'Moo Moo'],
['Oreo', 'Maggie'],
['Millie', 'Florence', 'Milkshake'],
['Lola']]

我试图创建一个函数来找到下一个最适合子条目的函数。例如,如果子列表的第一个元素是' Herman' (重量为7吨),我需要找到最接近10的值的下一个键,在这种情况下是Moo Moo' (重量3吨)。所以,这是我写的函数,以找到下一个拟合:

def findNextFit(adict, val, limit=10):             
       v=list(adict.values())               # list of the dict's values
       k=list(adict.keys())                 # list of the dict's keys
       diff = limit - val                   # value we are looking for

       if diff in v:                        # Perfect fit.
           return k[diff]

       elif diff not in v or diff < 0:      # No fit. 
           return False

       else:               # Difference is positive but not a perfect fit
           vfit = [i for i in v if i < diff]    # list of candidates
           return k[max(vfit)]                  # key with maximum value

当我测试这个功能时,我得到一个意想不到的结果:

>>> findNextFit(cows, 7, 10)
'Lola'

我应该得到的结果&#39; Moo Moo&#39;。

任何人都可以指出我在这个findNextFit函数中做错了什么?我一整天都在努力,而且我的想法已经不多了。

3 个答案:

答案 0 :(得分:0)

如果您完全符合要求,则必须将k中的元素放在v中该值的索引位置,这样您就错过了索引查找:

   if diff in v:                        # Perfect fit.
       return k[v.index(diff)]

如果第一次测试失败,您将遇到的其他问题与您的下一次测试相关联,该测试始终为True。您的else子句无法访问。

答案 1 :(得分:0)

您的问题在这里:

 if diff in v:                        # Perfect fit.
       return k[diff]

diff不一定是具有值diff的条目的相应键的索引。

您可以使用索引*方法解决此问题:

if diff in v:
    return k[v.index(diff)]

同样在您的第三个条件中,您必须执行:return k[v.index(max(fit))]

此外,您的第二个条件不应该是或者更确切地说是和。

所有修复:

def findNextFit(adict, val, limit=10):             
     v=list(adict.values())               # list of the dict's values
     k=list(adict.keys())                 # list of the dict's keys
     diff = limit - val                   # value we are looking for

     if diff in v:                        # Perfect fit.
         return k[v.index(diff)]

     elif diff < 0:      # No fit. Don't need to check if diff not in v because earlier if wouldve caught this case
         return False

     else:               # Difference is positive but not a perfect fit
         vfit = [i for i in v if i < diff]      # list of candidates
         if not vfit: return False
         return k[v.index(max(vfit))]                  # key with maximum value

答案 2 :(得分:0)

反转奶牛可能会更好:

cows = {'Herman': 7, 'Moo Moo': 3, 'Betsy': 9, 'Lola': 2, 'Milkshake': 2, 'Florence': 2, 'Henrietta': 9, 'Maggie': 3, 'Millie': 5, 'Oreo': 6}

作为

{2: ['Lola', 'Milkshake', 'Florence'], 3: ['Moo Moo', 'Maggie'], 5: ['Millie'], 6: ['Oreo'], 7: ['Herman'], 9: ['Betsy', 'Henrietta']}

然后你可以把你的功能写成:

cows = {'Herman': 7, 'Moo Moo': 3, 'Betsy': 9, 'Lola': 2, 'Milkshake': 2, 'Florence': 2, 'Henrietta': 9, 'Maggie': 3, 'Millie': 5, 'Oreo': 6}

def invert(d):
    i={}
    for k,v in d.iteritems():
        i.setdefault(v,[]).append(k)
    return i

inverted_cows = invert(cows)
# inverted_cows is a dictionary that has weights as keys and lists of cows as values

def findNextFit(adict, val, limit=10):
       diff = limit - val                   # value we are looking for

       if diff in adict:                        # Perfect fit.
           return adict[diff][0]

       elif diff <= 0:      # No fit. 
           return False

       else:               # Difference is positive but not a perfect fit
           vfit = [i for i in adict if i < diff]    # list of candidates
           if not vfit:
               return False
           return adict[max(vfit)][0]                  # key with maximum value

print findNextFit(inverted_cows, 7, 10)

这会打印Moo Moo。因为我们贪婪并且把两头奶牛中的第一头带到了相同的重量。