2015-04-03 118 views
6

我有一個元組列表,例如:Python:通過元組列表搜索

>>> 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的方法呢?

回答

7

試試這個:

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

使用next()的優勢在於我們只是遍歷所需要的最小數量的元素來找到我們正在尋找的東西,所以不,它不等同於使用列表理解創建一個全新列表,然後返回第一個元素。

+0

噢......所以這與上次嘗試更加一致,get()函數也停止了找到的元素。 – Jens 2015-04-03 02:39:06

+0

@Jens是的,它們是等效的 – 2015-04-03 02:47:51

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' 

注意,這會讓StopIteration異常,如果沒有找到,除非default提供:

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

這與第一個列表理解中的'[0]'索引是同義的,所以不是真的*和我得到的很不一樣? – Jens 2015-04-03 02:35:31

+1

@Jens Oscar剛剛提供瞭解釋,請查看。我想你應該接受他的回答。 – alecxe 2015-04-03 02:37:28

1

這取決於如何支付,空間或時間。你不可能有兩個。

1如果我們要加快:

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

2如果空間有限,嘗試其他答案的旁邊或你的循環。

+0

我不遵循1:構建字典需要對列表進行完整迭代,然後進行字典查找。此外,使用'get()'方法是最昂貴的字典查找(請參閱[this thread](http://stackoverflow.com/questions/9358983/python-dictionary-and-default-values#17501506)) 。那麼 - 如何加速使用'next()'? – Jens 2015-04-03 15:51:47

+0

鏈接主題緩慢的原因是數據太小,而成本是函數調用。但是,如果數據或元組爲百萬或大,哈希映射或集合的特徵將像O(1)一樣加速,而不像其他方法O(n)(例如next(x for x in l if x [1] == 2)[0]) – flycee 2015-04-03 16:11:42

+0

同意,如果你穩定查找而不是結構。不幸的是,就我而言,我需要遍歷不斷變化的元組列表。 – Jens 2015-04-03 16:13:40