简体   繁体   中英

How to find the index of the element in a list that first appears in another given list?

a = [3, 4, 2, 1, 7, 6, 5]
b = [4, 6]

The answer should be 1. Because in a, 4 appears first in list b, and it's index is 1.

The question is that is there any fast code in python to achieve this?

PS: Actually a is a random permutation and b is a subset of a, but it's represented as a list.

If b is to be seen as a subset (order doesn't matter, all values are present in a ), then use min() with a map() :

min(map(a.index, b))

This returns the lowest index. This is a O(NK) solution (where N is the length of a , K that of b ), but all looping is executed in C code.

Another option is to convert a to a set and use next() on a loop over enumerate() :

bset = set(b)
next(i for i, v in enumerate(a) if v in bset)

This is a O(N) solution, but has higher constant cost (Python bytecode to execute). It heavily depends on the sizes of a and b which one is going to be faster.

For the small input example in the question, min(map(...)) wins:

In [86]: a = [3, 4, 2, 1, 7, 6, 5]
    ...: b = [4, 6]
    ...:

In [87]: %timeit min(map(a.index, b))
    ...:
608 ns ± 64.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [88]: bset = set(b)
    ...:

In [89]: %timeit next(i for i, v in enumerate(a) if v in bset)
    ...:
717 ns ± 30.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In one line :

print("".join([str(index) for item in b for index,item1 in enumerate(a) if item==item1][:1]))

output:

1

In detail :

a = [3, 4, 2, 1, 7, 6, 5]
b = [4, 6]

new=[]
for item in b:
    for index,item1 in enumerate(a):
        if item==item1:
            new.append(index)

print("".join([str(x) for x in new[:1]]))

For little B sample, the set approach is output dependent, execution time grow linearly with index output. Numpy can provide better solution in this case.

N=10**6
A=np.unique(np.random.randint(0,N,N))
np.random.shuffle(A)
B=A[:3].copy()
np.random.shuffle(A)

def find(A,B):
    pos=np.in1d(A,B).nonzero()[0]
    return pos[A[pos].argsort()][B.argsort().argsort()].min()


def findset(A,B):
    bset = set(B)
    return  next(i for i, v in enumerate(A) if v in bset)

#In [29]: find(A,B)==findset(A,B)
#Out[29]: True
#In [30]: %timeit findset(A,B)
# 63.5 ms ± 1.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 
# In [31]: %timeit find(A,B)
# 2.24 ms ± 52.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM