获取包含子字符串的第一个列表索引?

52
对于列表,方法list.index(x)返回第一个值为x的项在列表中的索引。但是如果我想查看列表项内部,而不仅仅是整个项,我该如何使用Python最好的方法进行操作?
例如:
l = ['the cat ate the mouse',
     'the tiger ate the chicken',
     'the horse ate the straw']

如果提供参数tiger,这个函数会返回1

11个回答

42
一个非常简单的方法:
def index_containing_substring(the_list, substring):
    for i, s in enumerate(the_list):
        if substring in s:
              return i
    return -1

1
Python是一种非常优秀的编程语言,但它没有内置支持这样的功能。️ - TheEagle

39

用一行代码:

index = [idx for idx, s in enumerate(l) if 'tiger' in s][0]

如果有NA,它将无法运行。如何考虑这种情况? - Julien

7
变化的abyx解决方案(优化以在找到匹配项时停止)
def first_substring(strings, substring):
    return next(i for i, string in enumerate(strings) if substring in string)

如果您的版本低于2.6,您需要在末尾加上next()
def first_substring(strings, substring):
    return (i for i, string in enumerate(strings) if substring in string).next()

3
def find(l, s):
    for i in range(len(l)):
        if l[i].find(s)!=-1:
            return i
    return None # Or -1

3

这真的非常流畅,而且相当高效。

>>> def find(lst, predicate):
...     return (i for i, j in enumerate(lst) if predicate(j)).next()
... 
>>> l = ['the cat ate the mouse','the tiger ate the chicken','the horse ate the straw']
>>> find(l, lambda x: 'tiger' in x)
1

唯一的问题是,如果未找到该项,则会引发StopIteration错误(不过这很容易解决)。


1
可以避免StopIteration异常: return next((i for i, j in enumerate(lst) if predicate(j)), -1) (Python 2.6+) - vsvasya

2
def first_substring(strings, substring):
    return min(i for i, string in enumerate(strings) if substring in string)

注意:如果找不到匹配项,这将引发 ValueError ,在我看来这是更好的选择。

花哨但不高效,因为它测试列表的所有元素,而不管之前是否已经找到了文本。此外,Python的'something'.find(s)函数在未找到匹配项时返回-1,所以我认为这是符合Python风格的。 - Etienne Perot
在Python 2.6中无法工作。您不能在min()中同时使用可迭代对象和额外参数。@Etiene:这是一个生成器表达式,而不是列表推导式,因此它不会生成所有内容。 - Max Shawabkeh
@Etienne - 过早优化是万恶之源等等。 @Max - 你是正确的,已修正。 - abyx

2

在我看来,这行代码只会找到第一个出现的匹配项,而不是处理整个列表。

index = next((i for i in enumerate(l) if "tiger" in i[1]),[-1,-1])[0]


1

我只想获取文本,如果未找到该项,则不引发异常

search = 'a'
next((s for s in ["aa",'c'] if search in s), None)

search = 'b'
next((el for el in ["aa",'c'] if search in el), None)

这是我希望能够本地实现的事情之一。


0

@kennytm提供了一个非常好的答案,帮助了我;为了从他们的答案中构建一个允许正则表达式的函数,我写了以下代码:

def substringindex(inputlist, inputsubstring):
    s = [x for x in inputlist if re.search(inputsubstring, x)]

    if s != []:
        return (inputlist.index(s[0]), s[0])
    return -1

这个函数的工作方式与他们的完全相同,但支持正则表达式。


0
  >>> li = ['my','array','with','words']
  >>> reduce(lambda tup, word: (tup[0], True) if not tup[1] and word  == 'my' else (tup[0]+1 if not tup[1] else tup[0], tup[1]), li, (0, False))[0]
  0
  >>> reduce(lambda tup, word: (tup[0], True) if not tup[1] and word  == 'words' else (tup[0]+1 if not tup[1] else tup[0], tup[1]), li, (0, False))[0]
  3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接