代码之家  ›  专栏  ›  技术社区  ›  Wall-E

数组中满足条件的映射位置

  •  1
  • Wall-E  · 技术社区  · 6 年前

    给定一个逻辑数组(真/假值)和一个可能不从0开始的索引范围,我想创建一个与该范围大小相同的新数组,其中每个元素都包含前一个最接近的真的索引。

    逻辑阵列示例,例如:

    [1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]
    

    以及指数子集:
    [0, 1, 2, 3, 4, 5, 6, 7] (此处,从0开始,但可能不必)

    结果将是:

    [0, 0, 0, 3, 4, 5, 5, 7]
    

    我有一个可行的解决方案(见下文),但考虑到阵列的大小可能从数千到数百万不等,我正在寻找更快和/或更优雅和/或更可读的替代方案。

    import numpy as np
    
    def map_nearest_preceding_true_indices(tmask, irange):
    
        true_indices = np.where(tmask)[0]
        mapped_indices = np.empty(len(irange), dtype=np.int)
    
        for i, index in enumerate(irange):
            index_loc = np.where(true_indices <= index)[0][-1]
            mapped_indices[i] = true_indices[index_loc]
    
        return mapped_indices
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Divakar    6 年前

    这是一个矢量化的解决方案 np.searchsorted -

    def map_locations(tmask, irange, invalid_index=-1):
        idx = np.where(tmask)[0]
        sidx = np.searchsorted(idx, irange, 'right')-1
        return np.where(sidx==-1,invalid_index, idx[sidx])
    

    运行示例-

    In [124]: # Considering a more generic case
         ...: tmask = np.array([1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0], dtype=bool)
         ...: irange = np.array([4, 8, 11, 18])
    
    In [125]: map_locations(tmask, irange, invalid_index=-1)
    Out[125]: array([4, 7, 9, 9])
    
    In [129]: # Original case with first mask element being false
         ...: tmask = np.array([0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0], dtype=bool).tolist()
         ...: irange = np.array([0, 1, 2, 3, 4, 5, 6, 17]).tolist()
    
    In [130]: map_locations(tmask, irange, invalid_index=-1)
    Out[130]: array([-1, -1, -1,  3,  4,  5,  5,  9])
    
        2
  •  1
  •   agubelu    6 年前

    了解一行列表:

    data = [1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]
    indices = [0, 1, 2, 3, 4, 5, 6, 7]
    
    nearest_true = [next(v for v in range(ind, -1, -1) if data[v]) for ind in indices]
    

    对于索引数组中的每个索引, next 从该索引开始向后遍历数据数组,并返回包含truthy值的数据数组的第一个索引。

    然而,正如注释中所讨论的,如果任何索引处或后面没有至少一个truthy值,则此代码将失败。我们可以通过为 next() 将其作为第二个参数传递,在这种情况下,我们必须将生成器括起来,因为它不再是唯一的参数:

    NOT_FOUND = -1
    nearest_true = [next((v for v in range(ind, -1, -1) if data[v]), NOT_FOUND) 
                    for ind in indices]
    

    然后,输出 data = [0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0] 可能是 [-1, -1, -1, 3, 4, 5, 5, 7]