我有一个将id(整数)映射到数字(double)的字典结构。这些数字实际上是一个项目的权重。
我正在编写一个函数,允许我获取给定权重的id(如果在dict中找到权重,否则,它将返回下一个最接近的 id (即最接近的)重量。
这是我到目前为止所做的:
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
我不确定逻辑是否正确(尤其是我获得最小的deviatioon)。无论如何,即使逻辑是正确的,这似乎是一种过于复杂的做事方式。有没有更优雅/ pythonic的方式这样做?
在我的脑海中,我认为一种更加pythonic /更优雅的方式就是将自定义函数传递给min
函数 - 不知道是否可能......
[[更新]]
我正在运行Python 2.6.5
答案 0 :(得分:4)
尝试按重量与目标值的距离对项目进行排序:
from operator import itemgetter
distances = ((k, abs(v - value)) for k, v in bucketed_items_dict.items())
return min(distances, key=itemgetter(1))[0]
或者使用lambda函数而不是itemgetter:
distances = ((k, abs(v - value)) for k, v in bucketed_items_dict.items())
return min(distances, key=lambda x:x[1])[0]
答案 1 :(得分:3)
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]
或简而言之:
def getBucketIdByValue(bucket, value):
return min((abs(number-value),id) for id,number in bucket.items())[1]
此函数使用存储桶创建id / number对,然后创建一个距离/ id对的迭代器,然后得到它的第一个最小对,最后提取该对的id并返回它。
距离定义为数字与所寻求值之差的绝对值。
最小值定义为距离最短的对。如果还有更多,则返回具有最低id的对。
答案 2 :(得分:2)
您可以使用排序键中的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
这样你只需要检查2个重量并找到最好的重量。排序和二进制搜索可能比计算所有权重更快并找到最佳权重。
答案 3 :(得分:1)
我还会考虑bisect
模块。