简体   繁体   English

Python:确定字典中数字最接近匹配项的优雅方法

[英]Python: Elegant way of determining the nearest match for numbers in a dictionary

I have a dictionary structure that maps an id (integer) into a number (double). 我有一个字典结构,可将id(整数)映射为数字(双精度)。 The numbers are actually weights of an item. 数字实际上是一件物品的重量。

I am writing a function that will allows me to fetch the id of a given weight (if the weight is found in the dict, else, it will return the id of the next closest (ie nearest matching) weight. 我正在编写一个函数,该函数将允许我获取给定权重的ID(如果在dict中找到了权重,否则,它将返回下一个最接近(即最匹配的)权重的ID

This is what I have so far: 这是我到目前为止的内容:

def getBucketIdByValue(bucketed_items_dict, value):
    sorted_keys = sorted(bucketed_items_dict.keys())
    threshold = abs(bucketed_items_dict[sorted_keys[-2]] -bucketed_items_dict[sorted_keys[-1]]) # determine gap size between numbers

    # create a small dict containing likely candidates
    temp = dict([(x - value),x] for x in bucketed_items_dict.values() if abs(x - value) <= threshold)
    print 'DEBUG: Deviations list: ', temp.keys()
    smallest_deviation = min(temp.keys()) if value >= 0 else max(temp.keys()) # Not sure about this ?
    smallest_deviation_key = temp[smallest_deviation]
    print 'DEBUG: found bucketed item key:',smallest_deviation_key
    return smallest_deviation_key

I'm not sure the logic is actually correct (esp. where I obtain the smallest deviatioon). 我不确定逻辑是否正确(尤其是在获得最小偏差的地方)。 In any event, if even the logic is correct, this seems an overly complicated way of doing things. 无论如何,即使逻辑是正确的,这似乎也是一种过于复杂的处理方式。 Is there a more elegant/pythonic way of doing this? 有没有更优雅/ pythonic的方法来做到这一点?

Off the top of my head, I think a more pythonic/elegant way would be to do something like passing a custom function to the min function - don't know if that is possible... 我想不起来,我想一种更pythonic /优雅的方法是做类似将自定义函数传递给min函数的事情-不知道这是否可行...

[[Update]] [[更新]]

I am running Python 2.6.5 我正在运行Python 2.6.5

Try sorting the items by the distance of their weight to your target value: 尝试按重量与目标值的距离对物品进行排序:

from operator import itemgetter
distances = ((k, abs(v - value)) for k, v in bucketed_items_dict.items())
return min(distances, key=itemgetter(1))[0]

Or using a lambda function instead of itemgetter: 或使用lambda函数代替itemgetter:

distances = ((k, abs(v - value)) for k, v in bucketed_items_dict.items())
return min(distances, key=lambda x:x[1])[0]
def getBucketIdByValue(bucket, value):
    distances = [( id , abs( number - value ) ) for id , number in bucket.items()]
    swapped = [( distance , id ) for id , distance in distances]
    minimum = min ( swapped )
    return minimum[1]

Or in short: 或简而言之:

def getBucketIdByValue(bucket, value):
    return min((abs(number-value),id) for id,number in bucket.items())[1]

This function uses the bucket to create id/number pairs, then creates an iterator of distance/id pairs, then gets the first minimum pair of it and finally extract the id of that pair and returns it. 此函数使用存储桶创建ID /数字对,然后创建距离/ ID对的迭代器,然后获取它的第一个最小对,最后提取该对的ID并返回它。

The distance is defined as the absolute value of the difference between the number and the sought-for value. 距离定义为数字与所需值之差的绝对值。

The minimum is defined as the pair with the lowest distance. 最小值定义为距离最小的线对。 If there are more, the pair with the lowest id is returned. 如果还有更多,则返回ID最低的货币对。

You can find the index of closest weight using bisect in sorted keys: 您可以使用bisect在排序键中找到最接近权重的索引:

import bisect

def bisect_weight(sorted_keys, value):
    index = bisect.bisect(sorted_keys, value)
    # edge cases
    if index == 0: return sorted_keys[0]
    if index == len(sorted_keys): return sorted_keys[index - 1]
    minor_weight = sorted_keys[index - 1]
    greater_weight = sorted_keys[index]

    return minor_weight if abs(minor_weight - value) < abs(greater_weight - value) else greater_weight

This way you just need to check 2 weights and find the best one. 这样,您只需要检查2个权重并找到最佳权重即可。 Sorting and binary searching are probably faster than calc all weights and find the best one. 排序和二进制搜索可能比计算所有权重并找到最佳权重要快。

我还将考虑bisect模块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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