3

我有一个字典结构,可以将 id(整数)映射为数字(双精度)。这些数字实际上是物品的重量。

我正在编写一个函数,它允许我获取给定权重的 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

我不确定逻辑是否正确(尤其是我获得最小偏差的地方)。无论如何,即使逻辑是正确的,这似乎也是一种过于复杂的做事方式。有没有更优雅/pythonic的方式来做到这一点?

在我的脑海中,我认为一种更 Pythonic/优雅的方式是做一些事情,比如将自定义函数传递给min函数 - 不知道这是否可能......

[[更新]]

我正在运行 Python 2.6.5

4

4 回答 4

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]
于 2012-07-01T17:40:05.097 回答
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 的对。

于 2012-07-01T17:45:33.230 回答
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 个权重并找到最好的一个。排序和二进制搜索可能比计算所有权重并找到最佳权重更快。

于 2012-07-01T17:57:13.717 回答
1

我也会考虑bisect模块。

于 2012-07-01T17:52:35.163 回答