【问题标题】:How to find the index of the element in a list that first appears in another given list?如何在列表中查找首先出现在另一个给定列表中的元素的索引?
【发布时间】:2018-04-02 09:29:23
【问题描述】:
a = [3, 4, 2, 1, 7, 6, 5]
b = [4, 6]

答案应该是1。因为在a中,4在列表b中首先出现,它的索引是1。

问题是python中有没有快速的代码来实现这一点?

PS:其实a是一个随机排列,b是a的一个子集,但是它表示为一个列表。

【问题讨论】:

  • 那么b = [6, 4]的答案应该是一样的吗?你自己试过了吗?
  • b 是否总是一个子集,或者b 中的值可能不在a 中?
  • 那么,你基本上想要a.index(b[0])
  • @cᴏʟᴅsᴘᴇᴇᴅ:看我的问题,我不这么认为。
  • @Martijn Pieters 是对的。

标签: python list numpy indexing set


【解决方案1】:

对于小 B 样本,设置方法取决于输出,执行时间随索引输出线性增长。在这种情况下,numpy 可以提供更好的解决方案。

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)

【讨论】:

    【解决方案2】:

    一行:

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

    输出:

    1
    

    详细:

    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]]))
    

    【讨论】:

    • 这不会产生 first 索引。
    • 这仍然没有给你最低的索引。如果a = [6, 4] 你会得到错误的答案。
    • 为什么要切片并转换为字符串并加入?为什么不直接使用[0]
    • 哪里错了,如果 a= [6,4] 那么它给出答案 5 这是第一个元素的索引 6 ,因为 OP 说他想要一个像1 这样回答,所以我就加入它,;)
    • 它不应该,它应该产生1,因为这是第一个匹配索引。否则,您的代码是一种非常昂贵的拼写 a.index(b[0]) 的方式;如果你只想要第一个结果,为什么要循环
    【解决方案3】:

    如果将b 视为一个子集(顺序无关紧要,所有值都存在于a 中),那么将min()map() 一起使用:

    min(map(a.index, b))
    

    这将返回最低索引。这是一个 O(NK) 的解决方案(其中 N 是 a 的长度,K 是 b 的长度),但所有循环都在 C 代码中执行。

    另一种选择是将a 转换为一个集合并在enumerate() 上的循环上使用next()

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

    这是一个 O(N) 解决方案,但具有更高的恒定成本(要执行的 Python 字节码)。这在很大程度上取决于ab 的大小,哪个更快。

    对于问题中的小输入示例,min(map(...)) 获胜:

    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)
    

    【讨论】:

      猜你喜欢
      • 2015-06-09
      • 2019-10-28
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      • 1970-01-01
      • 1970-01-01
      • 2011-08-17
      • 2014-12-21
      相关资源
      最近更新 更多