在列表中查找子列表的索引

Find index of a sublist in a list

正在尝试查找包含某个元素的子列表的索引。我不确定如何准确说明问题(这可能是我在手册中忽略它的原因),但我的问题是:

list1 = [[1,2],[3,4],[7,8,9]]

我想找到 list1 中出现 7 的第一个子列表(在本例中索引为 2,但 lll 可能会非常非常长)。 (情况是每个数字将只出现在 1 个子列表中——或者根本不出现。而且这些只是整数列表) IE。像

这样的函数
spam = My_find(list1, 7)

会给垃圾邮件 = 2 我可以尝试循环制作布尔索引

[7 in x for x in lll]

然后 .index 找到 'true' -(根据 Most efficient way to get indexposition of a sublist in a nested list) 然而,必须建立一个新的布尔列表确实效率低下..

我的代码从 list1 开始,它相对较小,但它不断增加(最终将有 100 万个数字排列在 list1 的大约 5000 个子列表中

有什么想法吗?

I could try looping to make a Boolean index

[7 in x for x in lll]

and then .index to find the 'true' … However surely having to build a new boolean list is really inefficient

你离这里很近了。

首先,为了避免构建列表,使用生成器表达式而不是列表理解,只需将 [] 替换为 ()

sevens = (7 in x for x in lll)

但是当你有一个任意的可迭代对象而不是一个列表时,你如何做相当于 .index 的事情呢?您可以使用 enumerate 将每个值与其索引相关联,然后只需使用 filterdropwhile 或其他生成器表达式过滤掉非七,然后 next 会给你第一个 True.

的索引和值

例如:

indexed_sevens = enumerate(sevens)
seven_indexes = (index for index, value in indexed_sevens if value)
first_seven_index = next(seven_indexes)

如果你愿意,你当然可以将所有这些折叠成一个大表达式。

而且,如果您考虑一下,您实际上根本不需要那个初始表达式;您可以在后面的过滤步骤中执行此操作:

first_seven_index = next(index for index, value in enumerate(lll) if 7 in value)

当然,如果没有七,这将引发 StopIteration 异常而不是 ValueError 表达式,但除此之外,它与您的原始代码做同样的事情,但不构建列表, 并且在第一次匹配后没有继续测试值。