【问题标题】:What is the most efficient way to find the index of an element in a list, given only an element of a sublist (Python)仅给定子列表的元素(Python),查找列表中元素索引的最有效方法是什么
【发布时间】:2015-12-26 04:27:23
【问题描述】:

即是否存在类似以下内容?

lst = [["a", "b", "c"], [4,5,6],"test"]
print getIndex(lst, "a")
>>> 0
print getIndex(lst, 5)
>>> 1
print getIndex(lst, "test")
>>> 2

我知道常规的 index() 方法,但它只查找直接元素。我有一个粗略的解决方案,即创建一个新列表,解析超级列表并添加“y”或“n”,然后在该列表中查找“y”的索引,但我觉得有更好的方法。谢谢

【问题讨论】:

  • 不,没有内置功能可以做到这一点。这不是一个很难编写的函数,例如使用递归。但这是作业吗?
  • 不是。我刚找到一份需要大量 Python 的新工作,我正在努力学习。

标签: python list python-2.7 indexing nested-lists


【解决方案1】:

hellpanderrr's solution 有问题。它假定主列表元素只是列表或字符串。如果在主列表中存在另一种类型的列表中进行搜索,则会失败(in 操作引发TypeError)。例如:

lst2 = [["a", "b", "c"], [4, 5, 6], "test", 19]


>>> getIndex(lst2, 19)
# Ugly TypeError stack trace ensues

解决这个问题:

def getIndex2(lst, item):
    for n, i in enumerate(lst):
        try:
            if item == i or item in i:
                return n
        except TypeError:
            pass
    return None

现在:

>>> getIndex2(lst2, "test")
2
>>> getIndex2(lst2, 19)
3

有几种方法可以完成“等于或在”测试。这个解决方案直接通过,使用“获得宽恕而不是许可”成语来捕捉i 上的in 不适合类型的时间。也可以在in操作之前测试i的类型,或者直接询问i是否支持in操作。但是直接类型检查通常不受欢迎,Python 中的字符串和容器具有一些复杂的重叠功能。 “获得宽恕”方法可以更简单地优雅地处理这些问题。

请注意,这也显式处理未找到值的情况。

>>> print getIndex2(lst2, 333)
None

虽然不返回值的函数会隐式返回 None,但最好明确说明此类默认情况。

顺便说一句,这种方法处理两个级别。如果列表可以任意嵌套,则需要一种不同的方法,可能涉及递归。

【讨论】:

  • 顺便说一句,基于字符串和容器in 运算符的奇数重叠,该算法也存在一些退化情况。它们相当容易识别和严格测试,但会使代码更加复杂。
【解决方案2】:

使用生成器

例如在 >= Python 2.6 中,如果您知道该项目存在于子列表中:

idx = next(i for i,v in enumerate(lst) if item in v)

【讨论】:

  • 这不适用于@Jonathan Eunice 显示的案例。
  • 实际上,它通过了@JonathanEunices 解决方案中的测试,因为生成器在到达19 之前就停止了。但是,如果原始文件中有要忽略的随机非列表,我的解决方案可以修改为idx = next(i for i,v in enumerate(lst2) if hasattr(v, '__contains__') and item in v)idx = next(i for i,v in enumerate(lst2) if isinstance(v, list) and item in v)
  • 如果将搜索目标设置为item = 19,它仍然会抛出TypeError,不是吗?
  • 原始问题没有指定外部列表应该包含字符串或列表以外的元素。要求每个列表条目都有一个__contains__ 方法足以处理lst 条目是整数的情况。原始问题指定“......仅给定子列表的一个元素”,这足以假设所有列表条目也是列表(或字符串,在原始示例中)。否则,应该修改问题。
【解决方案3】:

尝试使用列表的默认函数:list.index

l = [[1,2,3], ['a', 'b', 'c']]

l[0].index(2)  # index 1
l[1].index('b') # index 1

This generates a "ValueError" if the item does not exist.

【讨论】:

    【解决方案4】:
    def getIndex(lst,item):
        for n,i in enumerate(lst):
            if (type(i) == list and item in i) or i == item
                return n
    getIndex(lst,'test')
    >>> 2
    

    【讨论】:

    • getIndex([["a", "b", "c"], [4, 5, 6], "test", 19], 19) 引发TypeError
    • 我们需要检查一下,比如if (type(i) == list and item in i) or i == item
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    • 2021-07-16
    • 1970-01-01
    相关资源
    最近更新 更多