Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 获取列表中第一个和最后一个公共元素索引的最快方法_Python_List_Numpy - Fatal编程技术网

Python 获取列表中第一个和最后一个公共元素索引的最快方法

Python 获取列表中第一个和最后一个公共元素索引的最快方法,python,list,numpy,Python,List,Numpy,我有两张分类表 x = [-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10] y = [3,4,5,6] 在这些x和y之间,我想返回imin=(6,0)和imax=(9,3)。如果这些列表不共享任何元素,我想返回imin=None和imax=None 解决办法是 def inds(x,y): arr = [(i,j) for i,xx in enumerate(x) for j,yy in enumerate(y) if xx==yy ] if arr!=[]:

我有两张分类表

x = [-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10]
y = [3,4,5,6]
在这些
x
y
之间,我想返回
imin=(6,0)
imax=(9,3)
。如果这些列表不共享任何元素,我想返回
imin=None
imax=None

解决办法是

def inds(x,y):
    arr = [(i,j) for i,xx in enumerate(x) for j,yy in enumerate(y) if xx==yy ]
    if arr!=[]: # to obtain proper None output
        imin = (min(i for i,_ in arr), min(j for _,j in arr))
        imax = (max(i for i,_ in arr), max(j for _,j in arr))
    else: 
        imin = None
        imax = None 
    return (imin,imax)
这做了很多不必要的计算(O(n**2)),是我的一个程序的瓶颈。有人能提出更快的建议吗

附加(非最小示例)信息

如果有帮助的话,我实际上有一个对象列表

objects = [(A1,B1),(A2,B2)] 
x
y
将是此对象列表中每个元素的属性,如下所示:

x = objects[0][0].attrib
y = objects[0][1].attrib
我真的想产生

[(imin1,imax1),(imin2,imax2)]
例如,它可能来自

def attribs(A,B):
    return (A.attrib,B.attrib)

[inds(*attribs(*v)) for v in objects]

注意:我添加了一个numpy标记,只是因为我愿意在速度更快的情况下使用numpy

这应该是你想要的

c = set(x).intersection(y)  # O(n) time
def get_first(l):
    return next((idx for idx, elm in enumerate(l) if elm in c), None)  # O(n) time
imin = (get_first(x), get_first(y))
imax = (len(x) - get_first(x[::-1]) - 1, len(y) - get_first(y[::-1]) - 1)

从这里开始,您可以进行一些调整,但它仍然会运行
O(n)

使用
np.intersect1d
并返回索引,您可以执行以下操作

idxes = np.stack(np.intersect1d(x,y, return_indices=True)[1:])
ix = tuple(idxes[:,0])
iy = tuple(idxes[:,-1])

>>> ix
(6, 0)
>>> iy
(9, 3)
解释

idxes
是一个二维索引数组,其中两个数组之间存在交点:

>>> idxes
array([[6, 7, 8, 9],
       [0, 1, 2, 3]])
所以你只需要第一次和最后一次

ix = tuple(idxes[:,0])
iy = tuple(idxes[:,-1])

您还可以对交叉点列表进行排序,并使用
.index()
查找索引

z = list(set(x).intersection(set(y))) # O(n)
z.sort() # O(nlogn)

imin = (x.index(z[0]), y.index(z[0])) # O(n)
imax = (x.index(z[-1]), y.index(z[-1])) # O(n)

这两个列表保证被排序吗?是的,它们总是被排序如何
iy=(9,3)
y
中没有
9
项不应该
iy=(0,3)
也不应该
ix=(6,9)
不是
(6,0)
?对不起,命名有点奇怪。iy实际上分别是x和y中最大元素的指数。我将编辑好我将删除我的答案并进行调整请注意,这是
numpy
中的一个非常新的功能,仅适用于
1.15.0版本
和higher@sacul我的np.intersect1d()没有返回值。你知道吗?我有
numpy
1.13.3
如果没有,我会非常惊讶。但是,有时候你不能真正确定使用
numpy
。最好的方法是运行
10、100、1000、10000的数组长度,并绘制对数梯度是的,我不知道如何检查numpy函数的时间复杂度,但是@AlexanderMcFarlane的绘制解决方案应该给出一个很好的提示,我想它们可能是
nlog(n)
因为我在源代码中看到,这里有一个排序算法,在感兴趣的系统大小上,它的速度提高了106倍:)