numpy 标识属于数组中不同序列的第一个元素

nbnkbykc  于 2023-02-23  发布在  其他
关注(0)|答案(2)|浏览(144)

我有一个排序后的整数数组(A),其中包含带间隔的升序序列。
A = array([1,2,3,4, 7,8,9, 23,24,25, 100])
我有一个数组(B),其中包含通过外部进程从A中选择的几个值。
B = array([1,2,23,25,100])
我想过滤掉B中属于A中相同序列的值,这样它就只返回每个唯一序列的前几个值
C = array([1,23,100])
我已经设法通过创建第二个列表来跟踪已经附加的内容,但这似乎有点笨拙,我想知道是否有更好的方法来做到这一点?

import numpy as np

A = np.array([1,2,3,4, 7,8,9, 23,24,25, 100])
B = np.array([1,2,23,25,100])
C = []

already_used_sequence = []

for x in enumerate(A):
    if x[0]-x[1] in already_used_sequence : #did we already group this sequence?
        pass
    elif len(np.intersect1d(B, x[1])) is not None: #is this value in B?
        for h in B:
            if h == x[1]: 
                C.append(x[1])
                already_used_sequence.append(x[0]-x[1])
C=np.array(C)
bvk5enib

bvk5enib1#

你需要一个groupby操作,这在numpy中是不容易完成的。一个选项是使用pandas

import pandas as pd

# convert to pandas Series
s = pd.Series(A)

# group by successive values
# keep the first found value per group
out = s[np.isin(A, B)].groupby(s.diff().gt(1).cumsum()).first().to_numpy()

输出:array([ 1, 23, 100])

bpsygsoo

bpsygsoo2#

需要指出的是,首先,尝试使用

for i, n in enumerate(my_iter):

而不是只有一个变量,然后必须访问位置和值与索引。
此外,intersection1d的len()永远不会是None,因为如果它不在B数组中,那么长度将是0,而不是None,而且你不必检查intersection,因为你无论如何都会经过这个数组。
考虑到所有这些因素,并在找到数字后添加break语句,它应该如下所示

for i, n in enumerate(A):
if i-n not in already_used_sequence :
    for h in B:
        if h == n: 
            C.append(n)
            already_used_sequence.add(i-n)
            break

我将already_used_sequence更改为set(),这在这个小输入中不会有任何区别,但在此上下文中,当您缩放时,它比列表更快。
如果你能保证B也是升序排列,你也可以

cur_index = 0
for i, n in enumerate(A):
    if n == B[cur_index]:
        cur_index += 1
        if i-n not in already_used_sequence:
            C.append(n)
            already_used_sequence.add(i-n)

这在较大的输入下是一个很大的速度提升,因为您不必在每次需要查找数字时都遍历B

相关问题