[英]fastest method to get indices of first and last common elements between lists
I have two sorted lists 我有两个排序列表
x = [-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10]
y = [3,4,5,6]
Between these x
and y
I would like to return imin = (6,0)
and imax = (9,3)
. 在这些
x
和y
之间,我想返回imin = (6,0)
和imax = (9,3)
。 If these lists do not share any elements, I would like to return imin = None
and imax = None
. 如果这些列表不共享任何元素,我想返回
imin = None
和imax = None
。
A solution is 一个解决方案是
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)
This does a lot of unnecessary computation (O(n**2)) and is a bottleneck of one of my programs. 这会做很多不必要的计算(O(n ** 2))并且是我的一个程序的瓶颈。 Can anyone suggest something faster?
任何人都能更快地提出建议
ADDITIONAL (NON-MINIMAL EXAMPLE) INFO 附加(非最小示例)信息
If it helps, I actually have a list of objects. 如果它有帮助,我实际上有一个对象列表。
objects = [(A1,B1),(A2,B2)]
x
and y
would be attributes of each element of this objects list like so: x
和y
将是此对象列表的每个元素的属性,如下所示:
x = objects[0][0].attrib
y = objects[0][1].attrib
and I actually want to generate 而我实际上想要生成
[(imin1,imax1),(imin2,imax2)]
Which could come, for example, from 例如,这可能来自
def attribs(A,B):
return (A.attrib,B.attrib)
[inds(*attribs(*v)) for v in objects]
note: I added a numpy tag just because I'm open to using numpy for this if it's faster. 注意:我添加了一个numpy标签只是因为如果它更快,我可以使用numpy。
This should be what you are after 这应该是你所追求的
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)
From here onwards you can do a few tweaks but it will still run O(n)
从这里开始你可以做一些调整,但它仍然会运行
O(n)
Using np.intersect1d
and returning the indices, you can do the following 使用
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)
Explanation 说明
idxes
is a 2d array of the indices where there are intersections between your two arrays: idxes
是索引的二维数组,其中两个数组之间存在交集:
>>> idxes
array([[6, 7, 8, 9],
[0, 1, 2, 3]])
So you can just take the first and last using 所以你可以采取第一次和最后一次使用
ix = tuple(idxes[:,0])
iy = tuple(idxes[:,-1])
You can also sort the intersection list and use .index()
to find out the indices. 您还可以对交集列表进行排序,并使用
.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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.