简体   繁体   中英

Python got no result and KeyError:1

def fre(dic, k):
    max_k = dic.keys()[0]
    max_v = dic.values()[0]
    while len(dic2) < k:
        for key, value in dic.items():
            if max_v < value:
                max_k = key
                max_v = value

        dic2[max_k] = max_v
        del dic[max_k]
    return dic2
# dic is a dictionary, k is an int

This question is to get the k biggest value in dic and get the matched key :value pairs. But I got running problem and got KeyError: 1.

The problem is that, each time through the loop, you leave max_k and max_v to the key-value pair you just found.

Since that was the maximum value, no other value in the dictionary will be larger. So at the end of the loop, you'll still have the same max_k and max_v . And then you'll try to del dic[max_k] again, and it raises a KeyError , because you already deleted it.

The solution is simple: take the code that sets max_k and max_v to the first element, and move it into the outer loop, so it runs every time instead of just the first time:

while len(dic2) < k:
    max_k = dic.keys()[0]
    max_v = dic.values()[0]

    for key, value in dic.items():
        if max_v < value:
            max_k = key
            max_v = value

    dic2[max_k] = max_v
    del dic[max_k]

But, while we're at it, there are easier (or at least harder-to-get-subtly-wrong) ways to do this.

The most obvious is to just sort the items by value , then take the first k :

import operator

def fre(dic, k):
    return dict(sorted(dic.items(), key=operator.itemgetter(1), reverse=True)[:k])

For more on how key functions work, and that itemgetter , see the Sorting HOWTO .

But you can make this more efficient. sorted obviously has to sort all n values, just to get the top k , so it takes O(n) space and O(n log n) time. If k is a lot smaller than n , you can do a lot better by using heapq.nlargest , which takes only O(k) space and O(n log k) time:

import heapq
import operator

def fre(dic, k):
    return dict(heapq.nlargest(k, dic.items(), key=operator.itemgetter(1)))

Either way, this doesn't delete the keys from dic ; if you need that, you can do that manually:

def fre(dic, k):
    dic2 = dict(heapq.nlargest(k, dic.items(), key=operator.itemgetter(1)))
    for key in dic2:
        del dic[key]
    return dic2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM