【问题标题】:Python: Search a sorted list of tuplesPython:搜索已排序的元组列表
【发布时间】:2017-07-17 23:55:54
【问题描述】:

有用信息:

有关如何对各种数据类型列表进行排序的信息,请参阅: How to sort (list/tuple) of lists/tuples?

.. 有关如何对排序列表执行二分查找的信息,请参阅:Binary search (bisection) in Python

我的问题:

如何巧妙地将二分搜索(或其他 log(n) 搜索算法)应用于某个数据类型的列表,其中键是数据类型本身的内部组件?为了简单起见,我们可以使用元组列表作为示例:

x = [("a", 1), ("b",2), ("c",3)]
binary_search(x, "b") # search for "b", should return 1
# note how we are NOT searching for ("b",2) yet we want ("b",2) returned anyways

为了进一步简化:我们只需要返回一个搜索结果,而不是多个如果例如 ("b",2) 和 ("b",3) 都存在。 p>

更好:

我们如何修改下面的简单代码来执行上述操作?

from bisect import bisect_left

def binary_search(a, x, lo=0, hi=None):  # can't use a to specify default for hi
    hi = hi if hi is not None else len(a)  # hi defaults to len(a)   
    pos = bisect_left(a, x, lo, hi)  # find insertion position
    return (pos if pos != hi and a[pos] == x else -1)  # don't walk off the end

请注意:我不是在寻找完整的算法本身。相反,我正在寻找一些 Python 的标准(ish)库和/或 Python 的其他功能的应用程序,以便我可以随时轻松地搜索一些任意数据类型的排序列表。

谢谢

【问题讨论】:

    标签: python algorithm list search


    【解决方案1】:

    利用字典排序如何处理长度不等的元组:

    # bisect_right would also work
    index = bisect.bisect_left(x, ('b',))
    

    有时将自定义序列类型提供给bisect 可能会很方便:

    class KeyList(object):
        # bisect doesn't accept a key function, so we build the key into our sequence.
        def __init__(self, l, key):
            self.l = l
            self.key = key
        def __len__(self):
            return len(self.l)
        def __getitem__(self, index):
            return self.key(self.l[index])
    
    import operator
    # bisect_right would *not* work for this one.
    index = bisect.bisect_left(KeyList(x, operator.itemgetter(0)), 'b')
    

    【讨论】:

    • 将简单二分查找算法的第5行修改为: pos = bisect_left(a, (x,), lo, hi) # 查找插入位置...没有达到想要的效果,返回a -1 未找到。
    • @StephenLasky:我只是向您展示如何找到索引。你的binary_search 函数有其他问题;例如,它直接比较xa[pos],所以它不明白它找到了正确的条目。
    • 我的错误,一切正常。出于好奇:您如何修改上述属性以搜索第 N 个位置?
    • @StephenLasky:我不确定你在说什么。
    【解决方案2】:

    如何将元组列表转换为字典?

    >>> d = dict([("a", 1), ("b",2), ("c",3)])
    >>> d['b'] # 2
    

    【讨论】:

    • 这里的问题是我正在处理大量列表(> 1,000,000),这种操作太慢了。不过,我很感谢您的回复。
    猜你喜欢
    • 2015-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 2014-05-11
    • 2021-09-11
    • 2014-05-01
    • 2021-12-12
    相关资源
    最近更新 更多