Python 在属性\u B排序列表中搜索属性\u A
在Python中,在根据属性排序的列表中搜索最有效的方法是什么?请参见下文,了解更精确的问题 例如:Python 在属性\u B排序列表中搜索属性\u A,python,list,search,attributes,Python,List,Search,Attributes,在Python中,在根据属性排序的列表中搜索最有效的方法是什么?请参见下文,了解更精确的问题 例如: class Any (object): def __init__(self, attr_a, attr_b): self.attr_a = attr_a self.attr_b = attr_b L = [Any(-3, 4), Any(-2, 1), Any(0, 2), Any(2, 1), Any(5, 6), Any(6, 3), Any(8,
class Any (object):
def __init__(self, attr_a, attr_b):
self.attr_a = attr_a
self.attr_b = attr_b
L = [Any(-3, 4), Any(-2, 1), Any(0, 2), Any(2, 1), Any(5, 6), Any(6, 3), Any(8, 2), Any(10, 1), Any(13, 5), Any(14, 3)]
L
根据属性attr\u a
进行排序。列表的所有Any
实例L
具有不同的attr\u a
值。搜索attr\u a
等于x
的对象的attr\u b
值的最有效方法是什么?要使用模块及其对分左
函数。在您的情况下,您需要在使用它之前提取密钥列表,有关详细说明,请参阅小节。如果这是不可接受的,那么您可以实现您自己版本的二进制搜索,这是一个简单的算法。您希望使用模块及其对分左
函数。在您的情况下,您需要在使用它之前提取密钥列表,有关详细说明,请参阅小节。如果这是不可接受的,那么您可以实现自己版本的二进制搜索,这是一个简单的算法。您可以采用二进制搜索来为您的属性值找到正确的任何对象。提供了一个起点:
def bisect_left(a, x, lo=0, hi=None, key=None):
if key is None: key = lambda v: v
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if key(a[mid]) < x: lo = mid+1
else: hi = mid
return lo
这将返回匹配的Any
的索引,或其attr\u a
值高于x
的下一个Any
对象的索引。您可能需要针对这些情况测试和/或调整算法。例如,您可以验证attr_a
是否确实匹配所需的值:
def find_by_x(L, x, key):
index = bisect_left(L, x, key=key)
if key(L[index]) != x:
raise IndexError('{} not found'.format(x))
return L[index]
演示:
>>来自操作员导入属性器
>>>L=[任何(-3,4)、任何(-2,1)、任何(0,2)、任何(2,1)、任何(5,6)、任何(6,3)、任何(8,2)、任何(10,1)、任何(13,5)、任何(14,3)]
>>>x=6
>>>左二等分(L,x,key=attrgetter('attr_a'))
5.
>>>L[bisect_left(L,x,key=attrgetter('attr_a'))].attr_b
3.
>>>通过(L,x,key=attrgetter('attr_a'))查找。attr_b
3.
>>>x=12
>>>通过(L,x,key=attrgetter('attr_a'))查找。attr_b
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第4行,按查找
未找到索引器:12
您应该采用二进制搜索,为您的attr\u a
值找到正确的任何
对象。提供了一个起点:
def bisect_left(a, x, lo=0, hi=None, key=None):
if key is None: key = lambda v: v
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if key(a[mid]) < x: lo = mid+1
else: hi = mid
return lo
这将返回匹配的Any
的索引,或其attr\u a
值高于x
的下一个Any
对象的索引。您可能需要针对这些情况测试和/或调整算法。例如,您可以验证attr_a
是否确实匹配所需的值:
def find_by_x(L, x, key):
index = bisect_left(L, x, key=key)
if key(L[index]) != x:
raise IndexError('{} not found'.format(x))
return L[index]
演示:
>>来自操作员导入属性器
>>>L=[任何(-3,4)、任何(-2,1)、任何(0,2)、任何(2,1)、任何(5,6)、任何(6,3)、任何(8,2)、任何(10,1)、任何(13,5)、任何(14,3)]
>>>x=6
>>>左二等分(L,x,key=attrgetter('attr_a'))
5.
>>>L[bisect_left(L,x,key=attrgetter('attr_a'))].attr_b
3.
>>>通过(L,x,key=attrgetter('attr_a'))查找。attr_b
3.
>>>x=12
>>>通过(L,x,key=attrgetter('attr_a'))查找。attr_b
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第4行,按查找
未找到索引器:12
排序列表最有效的搜索方法是对分算法。有关python的实现,请参见(查看投票数最多的一个)。您需要对其进行修改以找到attr_a,然后再获取attr_b。对于排序列表,最有效的搜索方法是对分算法。有关python的实现,请参见(查看投票数最多的一个)。你需要修改它来找到属性a,然后再得到属性b。这是一个非常好的解决方案!谢谢!很好的解决方案。我有点吃惊,因为我可以得到x
后面的attr\u a
值的索引(以及attr\u b
)!理论上这不应该是个问题,但我们永远不知道。。。我怎么能避免呢?如果没有任何
实例具有等于x
的attr\u a
,我如何获得错误消息?您必须验证该索引处的对象是否具有attr\u a
的预期值。我添加了一个先验证的示例函数。好的,我可以在之后检查它。非常感谢@martijnpieters给出的这个很棒的答案,这真是一个很棒的解决方案!谢谢!很好的解决方案。我有点吃惊,因为我可以得到x
后面的attr\u a
值的索引(以及attr\u b
)!理论上这不应该是个问题,但我们永远不知道。。。我怎么能避免呢?如果没有任何
实例具有等于x
的attr\u a
,我如何获得错误消息?您必须验证该索引处的对象是否具有attr\u a
的预期值。我添加了一个先验证的示例函数。好的,我可以在之后检查它。非常感谢您的回答@MartijnPieters