【问题标题】:Python: search through list of tuplesPython:搜索元组列表
【发布时间】:2015-06-08 03:28:16
【问题描述】:

我有一个元组列表,例如

>>> l = [ ("a",1), ("b",2), ("c",3) ]

我可以假设元素是独一无二的。现在我想得到那个元组的第一个元素,它的第二个元素是2(在这个例子中是'b')。第一次尝试是:

>>> [ x for x, y in l if y == 2 ][0]
'b'

考虑到这会创建第二个列表仅用于索引第 0 个元素,这似乎有点麻烦。另一种方法是反转给定列表l 中的所有元组并构建一个字典,然后索引该字典:

>>> dict([ (y, x) for x, y in l ])[2]
'b'

考虑到反转列表和创建字典所涉及的数据洗牌量,这似乎更加尴尬。最后,最冗长但可能最快的方法是简单地遍历列表:

>>> def get(l) :
...     for x, y in l :
...         if y == 2 : 
...             return x
...     assert not "Should not happen."
... 
>>> get(l)
'b'

我的问题是:有没有更好、更 Python 的方式来搜索这个列表?

【问题讨论】:

    标签: list search python-3.x tuples


    【解决方案1】:

    这取决于付款方式、空间或时间。你不能两者兼得。

    1 如果我们想加快速度:

    l = [ ("a",1), ("b",2), ("c",3) ]
    _dict = {k:v for v,k in l}
    print(_dict.get(2, None))
    

    2 如果空间有限,请尝试其他答案的下一个或您的循环。

    【讨论】:

    • 我不遵循 1:要构建字典,它需要对列表进行完整迭代,然后是字典查找。此外,使用get() 方法是最昂贵的字典查找(参见this thread)。那么 - 1 如何比使用 next() 加速?
    • link的topic之所以慢是因为数据太少,然后是函数调用的代价。但是如果数据或元组是百万或大,哈希映射或集合的特征将像 O(1) 一样加速,而不像其他方法 O(n) 那样(例如 next(x for x in l if x[1] == 2)[0])
    • 同意,如果您通过查找而不是构造来稳定。不幸的是,就我而言,我需要遍历不断变化的元组列表。
    【解决方案2】:

    试试这个:

    next(x for x in l if x[1] == 2)[0]
    

    使用next() 的优点是我们只迭代查找所需内容所需的最少元素数量,所以不,它不等同于使用列表推导式创建一个全新的列表然后返回第一个元素。

    【讨论】:

    • 哦...所以这与最后一次尝试更一致,get() 函数也与找到的元素停止。
    • @Jens 是的,它们是等价的
    【解决方案3】:

    你也可以使用next():

    In [1]: l = [("a", 1), ("b", 2), ("c", 3)]
    
    In [2]: next(a for a, b in l if b == 2)
    Out[2]: 'b'
    

    请注意,除非提供 default,否则如果找不到任何内容,它将引发 StopIteration 异常:

    In [3]: next(a for a, b in l if b == 100)
    ---------------------------------------------------------------------------
    StopIteration                             
    Traceback (most recent call last)
    <ipython-input-38-14fe91d87aab> in <module>()
    ----> 1 next(a for a, b in l if b == 100)
    
    StopIteration: 
    
    In [4]: next((a for a, b in l if b == 100), 0)
    Out[4]: 0
    

    【讨论】:

    • 这与第一个列表理解中的 [0] 索引同义,所以与我所拥有的相比,真的没有太大不同?
    • @Jens Oscar 刚刚提供了解释,请查看。我认为你应该接受他的回答。
    猜你喜欢
    • 1970-01-01
    • 2014-05-01
    • 2021-12-12
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 2018-08-05
    • 2011-03-06
    • 1970-01-01
    相关资源
    最近更新 更多