假设我的字典看起来像这样:
my_dict = {'bananas':'3', 'apples':'10', 'pears':'9', 'grapes':'2', 'oranges':'21', 'peaches':'12'}
我想创建一个函数,当用户输入水果x时,返回最接近水果x的2个水果。
例如,如果用户将苹果输入为x,则该函数将返回梨和桃子。
如果葡萄以x输入,香蕉和梨将被退回。
从算法上讲,这非常简单。我想知道是否有一种pythonic方式来实现这一目标。
答案 0 :(得分:1)
我认为你的意思是“概念上”它非常简单。但你仍然需要提出一个算法来做到这一点。
如果它实际上总是2个最接近的元素,那么到目前为止你可以有2个变量保持最接近和第二个最接近的匹配。然后遍历字典,对于您找到的每个水果,执行以下逻辑:如果比第一个最接近,则首先复制到最接近第二个,然后将新水果复制到第一个最接近的水果。否则,如果小于第二个最近,则在最接近的第二个上复制新的。
如果有可能推广到n个最接近的匹配,那么你可以这样做:创建一个heapq来保存n个最接近的匹配。通过字典迭代。在每一步,将(距离,果实)元组推入heapq。如果heapq的长度大于n,则从队列中弹出最大元素(最长距离)并丢弃它。最后,heapq将保存n个最接近的项目。
或者您可以使用列表推导来创建(距离,水果)对的列表,然后对其进行排序,然后获取n个最小的条目(在您的情况下n = 2)。
根据@ RoadRunner的建议,另一个选项是创建和存储(count,fruit)元组的排序列表(例如search_list = sorted([(c, f) for (f, c) in my_dict.items()])
。然后使用bisect模块中的bisect函数快速找到哪里(x_count,x)属于此列表。然后从那里向前或向后检查最多2个位置的距离,为这些候选者创建(x_count-fruit_count,fruit)对的(短)列表。然后对此列表进行排序并取前两项。
我没有提供完整的细节,因为这听起来有点像家庭作业,但希望这会给你一些想法。
答案 1 :(得分:1)
这是一种使用deques的简单方法。
<强>鉴于强>
import collections as ct
my_dict = {
"bananas":"3", "apples":"10", "pears":"9",
"grapes":"2", "oranges":"21", "peaches":"12"
}
<强>代码强>
def search_neighbors(query, sorted_iterable):
"""Return the nearest neighbors."""
# Build data structures
lookup_idx = {v[0]: i for i, v in enumerate(sorted_iterable)}
dq = ct.deque(sorted_iterable)
# Pop searched items from a deque
idx = lookup_idx[query]
dq.rotate(-idx)
left = dq.pop()
center = dq.popleft()
right = dq.popleft()
if left[-1] > right[-1]:
# Correction for min/max values
if center[-1] == min(d.values()):
left = dq.popleft()
else:
right = dq.pop()
return left, right
<强>演示强>
d = {k: int(v) for k, v in my_dict.items()}
sorted_items = sorted(d.items(), key=lambda x: x[-1])
对于大多数情况:
search_neighbors("apples", sorted_items)
# (("pears", 9), ("peaches", 12))
search_neighbors("bananas", sorted_items)
# (('grapes', 2), ('pears', 9))
search_neighbors("peaches", sorted_items)
# (('apples', 10), ('oranges', 21))
查询最小/最大值:
search_neighbors("grapes", sorted_items)
# (("pears", 9), ("bananas", 3))
search_neighbors("oranges", sorted_items)
# (('peaches', 12), ('apples', 10))
<强>详情
字典将数字字符串转换为整数,以便对其进行排序。排序的键在反向字典中编制索引以便更快地查找。已排序的项目将添加到双端队列中。将双端队列旋转到查询项目的位置后,弹出最近的邻居(左右)。如果检测到最小/最大值,即弹出项目的值不按顺序,则在任一方向上弹出下一个连续项目。注意:在此更正过程中,变量会被覆盖,不再是严格的左右方向。
有关deque.popleft()
的效果,请参阅此post。
答案 2 :(得分:0)
可以使用这样的东西,
你的范围非常疯狂,但我相信调整key-3
和key+4
会处理你的工作。
def near():
key = int(my_dict[input("Enter Key:")])
return [i for i in my_dict if int(my_dict[i]) in range(key-3,key+4)]
现在当你运行它时:
>>> near()
Enter Key:apples
['pears', 'peaches', 'apples']
>>>
您可以轻松地从列表中删除苹果,但这些都是为您准备的!
答案 3 :(得分:0)
这样的事情:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
intent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:+91100"));
startActivity(intent);
} else {
intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:+91100"));
startActivity(intent);
}
其工作原理如下:
from operator import itemgetter
def search(x, fruits):
# get the count of the fruit
count = fruits[x]
# get the rest of the elements
rest = {k: _ for k, _ in fruits.items() if k != x}
# dictionary that stores fruits count differences
diff = {_: abs(int(count) - int(v)) for _, v in rest.items()}
# get the top two closest fruits and store them in a set
top_two = {x for x, _ in sorted(diff.items(), key = itemgetter(1)) [:2]}
# return the top two closest
return [(x, fruits[x]) for x in fruits if x in top_two]
答案 4 :(得分:0)
以下是使用迭代器和第三方工具more_itertools.adajecent
的单独方法。此代码产生距离查询项目1或更远的邻居。
<强>代码强>
def search_neighbors(query, sorted_items, distance=1):
"""Yield neighboring items."""
if query in sorted_items[0] or query in sorted_items[-1]:
if query in sorted_items[-1]:
sorted_items = reversed(sorted_items)
sorted_iter = iter(sorted_items)
next(sorted_iter)
for _ in range(distance*2):
yield next(sorted_iter)
else:
pred = lambda x: x[0] == query
items = (item for bool_, item in mit.adjacent(pred, sorted_items, distance) if bool_)
for _ in range(distance):
yield next(items)
next(items)
for _ in range(distance):
yield next(items)
# Pre-build dictionaries
d = {k: int(v) for k, v in my_dict.items()}
sorted_items = sorted(d.items(), key=lambda x: x[-1])
<强>演示强>
项目根据其值进行排序。对于列表中的项目(远离两端),可以产生左右邻居。
>>> # Non-Terminal Items
>>> list(search_neighbors("apples", sorted_items))
[("pears", 9), ("peaches", 12)]
>>> list(search_neighbors("bananas", sorted_items))
[('grapes', 2), ('pears', 9)]
>>> list(search_neighbors("peaches", sorted_items))
[('apples', 10), ('oranges', 21)]
在列表末尾找到的项目会有不同的处理方式 - 连续项目可以正向或反向生成。
>>> # Terminal Items
>>> list(search_neighbors("grapes", sorted_items))
[("pears", 9), ("bananas", 3)]
>>> list(search_neighbors("oranges", sorted_items))
[('peaches', 12), ('apples', 10)]
对于终端查询, 2n
个邻居可以获得最远距离为n
的非终端查询,而2n
可用于终端查询。
>>> # Distance
>>> n = 2
>>> list(search_neighbors("apples", sorted_items, distance=n))
[('bananas', 3), ('pears', 9), ('peaches', 12), ('oranges', 21)]
>>> list(search_neighbors("grapes", sorted_items, distance=n))
[('bananas', 3), ('pears', 9), ('apples', 10), ('peaches', 12)]
如果距离大于已排序的可迭代,则迭代器会短路。
>>> # Early Termination
>>> list(search_neighbors("grapes", sorted_items, distance=10))
[('bananas', 3),
('pears', 9),
('apples', 10),
('peaches', 12),
('oranges', 21)]