在子子列表中找到元素的索引

3

我有一个这样的列表:

a = [[[0.0125, 6.6], [0.0125, 6.65], [0.0125, 6.7], [0.0125, 6.75], [0.0125, 6.8]], [[0.0185, 6.6], [0.0185, 6.65], [0.0185, 6.7], [0.0185, 6.75], [0.0185, 6.8]]]

ie: N 子列表(这里只有两个)和每个子列表中的 M 个子子列表(此示例中为五个)。每个元素/子子列表由两个浮点数组成。

我需要找到给定元素的索引,比如 [0.0185, 6.75]。在这种情况下,结果应该是:[1, 3]

我不能仅仅在 a 上应用 .index() 运算符,因为该元素位于其中一个子列表中,而且我不知道它在哪个子列表中,因此不能通过循环子列表并应用该运算符来查找该元素,因为如果找不到该元素,则会导致错误。


添加

我尝试了 zhangxaochen 和 DSM 的答案在一个更大的数组(16 个子列表和 70 个子子列表)中,看看哪个更快,这就是我得到的结果:

DSM: 4.31537628174e-05
zhangxaochen: 0.00113296508789

由于 DSM 的回答速度快了约 26 倍,所以我选择了它。感谢大家!


当你写“只有这两个”时,这是否意味着实际情况中会超过两个? - Tim Pietzcker
@Gabriel,你希望嵌套列表的索引如何返回? - thefourtheye
@thefourtheye 不是更多的嵌套子列表,而只是更多的列表(例如:40个子列表而不是2个子列表,60个子子列表而不是5个子子列表)。也许我表达得不太好,抱歉。 - Gabriel
4个回答

2

一种方法是使用nextenumerate

>>> a = [[[0.0125, 6.6], [0.0125, 6.65], [0.0125, 6.7], [0.0125, 6.75], [0.0125, 6.8]], [[0.0185, 6.6], [0.0185, 6.65], [0.0185, 6.7], [0.0185, 6.75], [0.0185, 6.8]]]
>>> search_for = [0.0185, 6.75]
>>> print next(((i,j) for i,x in enumerate(a) for j,y in enumerate(x) 
...             if y == search_for), None)
(1, 3)
>>> search_for = [0.0185, 99]
>>> print next(((i,j) for i,x in enumerate(a) for j,y in enumerate(x) 
...             if y == search_for), None)
None

但是,由于测试浮点数的相等性可能过于敏感,您可能希望使用 is_close(y, search_for) 函数替换 y == search_for,该函数允许一定的误差容忍度。使用 in.index 方法无法真正处理这种情况。


很遗憾,原po刚刚评论说这些列表可以被嵌套得更深。 - Tim Pietzcker
不,列表不会嵌套得更深。我说可以有更多的子列表和子子列表(甚至在这些子子列表中还有元素),但它们不会相互嵌套,只是它们的数量可以增加。 - Gabriel

2
我想使用numpy来完成这个任务:
In [93]: from numpy import *
    ...: a = [[[0.0125, 6.6], [0.0125, 6.65], [0.0125, 6.7], [0.0125, 6.75], [0.0125, 6.8]], [[0.0185, 6.6], [0.0185, 6.65], [0.0185, 6.7], [0.0185, 6.75], [0.0185, 6.8]]]
    ...: a=np.asarray(a)
    ...: needle=[0.0185, 6.75]
    ...: idx=nonzero(all(a==needle, axis=-1))
    ...: asarray(idx)[:,0]
    ...: 
Out[93]: array([1, 3])

我参考了以下文章:

Python/NumPy寻找子数组的第一个出现位置

https://github.com/numpy/numpy/issues/2269

通过这种方式,它可以处理深度嵌套的情况,例如a=[[[[your data...],[...]]]]是4级嵌套的,预期输出索引现在是(0,1,3)

In [95]: from numpy import *
    ...: a = [[[[0.0125, 6.6], [0.0125, 6.65], [0.0125, 6.7], [0.0125, 6.75], [0.0125, 6.8]], [[0.0185, 6.6], [0.0185, 6.65], [0.0185, 6.7], [0.0185, 6.75], [0.0185, 6.8]]]]
    ...: a=np.asarray(a)
    ...: needle=[0.0185, 6.75]
    ...: idx=nonzero(all(a==needle, axis=-1))
    ...: asarray(idx)[:,0]
Out[95]: array([0, 1, 3])

1
使用 next 和生成器表达式:
search = [0.0185, 6.75]

gen = ((ix,iy) for ix,outer in enumerate(a) for iy,inner in enumerate(outer) if inner == search)

next(gen,'not found')
Out[27]: (1, 3)

如果生成器在没有找到结果的情况下耗尽,则 next 返回其第二个参数(在本例中为'not found',可使用任何您想要使用的内容)。
如果上面的嵌套列表理解起来有困难,它在语法上等同于:
for ix,outer in enumerate(a):
    for iy,inner in enumerate(outer):
        if inner == search:
            yield (ix,iy)

0
在调用 .index() 之前,使用 in 测试成员身份。
def find(lst, needle):
    for i, sublist in enumerate(lst):
        if needle in sublist:
            return [i, sublist.index(needle)]

a = [[[0.0125, 6.6], [0.0125, 6.65], [0.0125, 6.7], [0.0125, 6.75], [0.0125, 6.8]], [[0.0185, 6.6], [0.0185, 6.65], [0.0185, 6.7], [0.0185, 6.75], [0.0185, 6.8]]]
element = [0.0185, 6.75]

print(find(a, element))

结果:

[1, 3]

inindex都是O(N) - thefourtheye
@thefourtheye 这是真的...有更快的方法吗?如果数据没有排序或者结构化,你必须读取每个元素直到找到你要查找的那个,对吧? - senshin
@thefourtheye 但它们都是内置方法,这意味着它们比Python循环更快地迭代列表。然而,确实可以使用sublist.find(needle)避免额外的迭代。或者在try块中使用sublist.index(needle) - Bakuriu

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