簡體   English   中英

獲取列表之間第一個和最后一個共同元素索引的最快方法

[英]fastest method to get indices of first and last common elements between lists

我有兩個排序列表

x = [-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10]
y = [3,4,5,6]

在這些xy之間,我想返回imin = (6,0)imax = (9,3) 如果這些列表不共享任何元素,我想返回imin = Noneimax = 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)] 

xy將是此對象列表的每個元素的屬性,如下所示:

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM