删除numpy数组的某些元素

2024-03-29 12:07:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个numpy数组ab。我有一个定义,它构造了一个数组c,其元素是数组中不同元素的所有可能和

import numpy as np

def Sumarray(a):
    n = len(a)

    sumarray = np.array([0]) # Add a default zero element
    for k in range(2,n+1):
        full = np.mgrid[k*(slice(n),)]
        nd_triu_idx = full[:,(np.diff(full,axis=0)>0).all(axis=0)]
        sumarray = np.append(sumarray, a[nd_triu_idx].sum(axis=0))

    return sumarray

a = np.array([1,2,6,8])
c = Sumarray(a)
print(d)

然后,我在cb的元素之间执行一个子集:isSubsetSum返回b的元素,求和后得到c[1]。假设我

c[0] = b[2] + b[3]

然后我想删除:

  1. 元素b[2]、b[3](简单位)和
  2. a的元素,求和后得到c[0]

从定义Sumarray可以看出,a的不同元素的和的顺序被保留,因此我需要实现一些映射。你知道吗

函数isSubsetSum

def _isSubsetSum(numbers, n, x, indices):
    if (x == 0):
        return True
    if (n == 0 and x != 0):
        return False
    # If last element is greater than x, then ignore it
    if (numbers[n - 1] > x):
        return _isSubsetSum(numbers, n - 1, x, indices)
    # else, check if x can be obtained by any of the following
    found = _isSubsetSum(numbers, n - 1, x, indices)
    if found: return True
    indices.insert(0, n - 1)
    found = _isSubsetSum(numbers, n - 1, x - numbers[n - 1], indices)
    if not found: indices.pop(0)
    return found

def isSubsetSum(numbers, x):
    indices = []
    found = _isSubsetSum(numbers, len(numbers), x, indices)
    return indices if found else None

Tags: numpy元素returnifdefnp数组full
1条回答
网友
1楼 · 发布于 2024-03-29 12:07:52

当您迭代所有可能的项数时,您也可以直接生成all可能的子集。你知道吗

这些可以方便地编码为数字0,1,2,。。。通过它们的二进制表示法:O表示完全没有项,1表示只有第一项,2表示只有第二项,3表示第一项和第二项,依此类推。你知道吗

使用此方案,从和索引中恢复项变得非常容易,因为我们只需获得二进制表示:

更新:我们可以用少量的额外代码来抑制1项和:

import numpy as np

def find_all_subsums(a,drop_singletons=False):
    n = len(a)
    assert n<=32 # this gives 4G subsets, and we have to cut somewhere
    # compute the smallest integer type with enough bits
    dt = f"<u{1<<((n-1)>>3).bit_length()}"
    # the numbers 0 to 2^n encode all possible subsets of an n
    # element set by means of their binary representation
    # each bit corresponds to one element number k represents the 
    # subset consisting of all elements whose bit is set in k
    rng = np.arange(1<<n,dtype=dt)
    if drop_singletons:
        # one element subsets correspond to powers of two
        rng = np.delete(rng,1<<np.arange(n))
    # np.unpackbits transforms bytes to their binary representation
    # given the a bitvector b we can compute the corresponding subsum
    # as b dot a, to do it in bulk we can mutliply the matrix of 
    # binary rows with a
    return np.unpackbits(rng[...,None].view('u1'),
                         axis=1,count=n,bitorder='little') @ a

def show_terms(a,idx,drop_singletons=False):
    n = len(a)
    if drop_singletons:
        # we must undo the dropping of powers of two to get an index
        # that is easy to translate. One can check that the following
        # formula does the trick
        idx += (idx+idx.bit_length()).bit_length()
        # now we can simply use the binary representation
    return a[np.unpackbits(np.asarray(idx,dtype='<u8')[None].view('u1'),
                           count=n,bitorder='little').view('?')]


example = np.logspace(1,7,7,base=3)
ss = find_all_subsums(example,True)
# check every single sum
for i,s in enumerate(ss):
    assert show_terms(example,i,True).sum() == s
# print one example
idx = 77
print(ss[idx],"="," + ".join(show_terms(example.astype('U'),idx,True)))

运行示例:

2457.0 = 27.0 + 243.0 + 2187.0

相关问题 更多 >