2012-09-18 28 views
4

在Python 2.7.x中,什麼是最好(最快)的方法來檢查嵌套元組中是否存在字符串(或任何其他數據類型)?查找Python中是否存在嵌套元組中的字符串

例如:

RECIPES = (
    ('apple', 'sugar', 'extreme_Force'), 
    ('banana', 'syrup', 'magical_ends'), 
    ('caramel', 'chocolate', 'pancake_MONSTER'), 
    ('banana',('someAnother','banana')) 
) 

此元組需要被檢查,如果banana出現在任何嵌套元組,並返回該位置索引,在此情況下1,0

此外,元組可以嵌套到任何深度。

+0

可能在每個元組中(頂級「RECIPES」中的數量和平均多少種成分)? – dbr

+3

我猜這個位置是'1,0'? –

+1

你的意思是嵌套到任何深度?你的例子是一個扁平的列表 - 如果你想要一個解決方案來處理它,你應該爲嵌套食譜提供一個數據結構和期望的返回值。 – Dave

回答

7

遞歸多位置索引:

import sys 
from collections import Sequence,defaultdict 

#making code python3-compatible 
if sys.version_info[0] == 3: 
    basestring = str 

def buildLocator(tree): 
    locator = defaultdict(list) 
    def fillLocator(tree, locator,location): 
     for index,item in enumerate(tree):    
      if isinstance(item,basestring): 
       locator[item].append(location+(index,)) 
      elif isinstance(item,Sequence): 
       fillLocator(item,locator, location+(index,)) 
    fillLocator(tree,locator,()) 
    return locator 

RECIPES = (
    ('apple', 'sugar', 'extreme_Force'), 
    ('banana', 'syrup', 'magical_ends'), 
    ('caramel', 'chocolate', 'pancake_MONSTER'), 
    ('banana',('someAnother','banana')) 
) 
locator = buildLocator(RECIPES) 

print(locator['banana']) 

打印

[(1, 0), (3, 0), (3, 1, 1)] 
+3

更好地使用'basestring',因爲它被標記爲python2.7 – mgilson

+0

@mgilson感謝您的評論。更新。 – Odomontois

+0

我以爲我是唯一一個把多餘的'如果sys.version_info [0]> = 3'保持向後兼容:) – mgilson

4

如果你只需要在第一場比賽的發電機可以做到這一點很好:

def find_location(text): 
    try: 
     return next((i, j) 
      for i, t in enumerate(RECIPES) 
      for j, v in enumerate(t) 
      if v == text) 
    except StopIteration: 
     return (None, None) # not found 

用法:

>>> find_location('banana') 
(1, 0) 
>>> find_location('apple') 
(0, 0) 
>>> find_location('chocolate') 
(2, 1) 
>>> find_location('spam') 
(None, None) 

注意,首先看重的是索引到全部測試RECIPES序列,第二是單個元組的索引; RECIPES[1][0] == 'banana'

+0

這是真棒,乾淨。但多位置解決方案是理想的解決方案。 :) 謝謝! –

1

使用for循環來查找項目是否存在,並在找到該項時立即中止該循環。

In [48]: RECIPES = (
    ....:  ('apple', 'sugar', 'extreme_Force'), 
    ....:  ('banana', 'syrup', 'magical_ends'), 
    ....:  ('caramel', 'chocolate', 'pancake_MONSTER'), 
    ....:) 

In [49]: for i,x in enumerate(RECIPES): 
    ....:  if 'banana' in x: 
    ....:   print i,x.index('banana') 
    ....:   break 
    ....:   
    ....:   
1 0 
+1

您每行搜索兩次;首先用'in'測試,然後用'.index()'。 –

+0

這也只適用於食譜嵌套1層的情況。對於任意嵌套,您需要更多的工作。 – mgilson

+0

@MartijnPieters,true,但它可能仍然很快,因爲我確定'in'和'index'都是高度優化的。與您的解決方案進行比較將會很有趣。 –

1

爲什麼不試試numpy

import numpy as np 
RECIPES = (
    ('apple', 'sugar', 'extreme_Force'), 
    ('banana', 'syrup', 'magical_ends'), 
    ('caramel', 'chocolate', 'pancake_MONSTER'), 
) 
np_recipes = np.array(recipes) 
indices = zip(*np.where(np_recipes == 'banana')) #[(1, 0)] 

這適用於你的例子,因爲數據是很好的命令。我想應該指出的是,這不適用於你所問的任意嵌套(但是如果其他人發現這個問題有類似的,更受限制的問題,我會把它留在這裏)。

+0

這很整齊。但是這裏的數據稍微有點亂。儘管如此,我仍會將其留待將來參考。你可以創建一個問題並自己回答以供參考。 –

0

這將找到遞歸第一次出現:當你說 「最快」,有多少項目是

RECIPES = (
    ('apple', 'sugar', 'extreme_Force'), 
    ('banana', 'syrup', 'magical_ends'), 
    ('caramel', 'chocolate', 'pancake_MONSTER'), 
) 

def find_str(seq, s): 
    for idx, item in enumerate(seq): 
     if hasattr(item, "__iter__"): 
      r = find_str(item, s) 
      if r is not None: 
       return [idx]+r 
     elif item == s: 
      return [idx] 

print find_str(RECIPES, "banana") # prints [1, 0] 
相關問題