比方说,我有一个包含允许和禁止区域的网格。
import numpy as np
forbidden = np.array([False, False, False, False, False, False, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, False, False, False, False, False, False,
False, False, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, False, False, False,
False, False, False, False, False, False, False, False, False,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, True, True, True, True, True, True, True,
True, True, True, True, True, False])
现在,我在(0,149)之间有一堆网格点。如果它们似乎在禁区中,我想“将它们移到左侧”,直到它们移出禁区。
例如,
idx = 13
forbidden[idx] # is True, hence we want to move to the left
forbidden[5] # is False, and it is the "first index" where this is such
同时
idx = 5
forbidden[idx] = # is False, so this index stays the way it is
因此,getCorrectIndex(13) == getCorrectIndex(5) == 5
。
一种低效率的编码方式:
def getCorrectIndex(idx, forbidden):
# this trusts that the forbidden[0] == False, which is Okay
for remove in range(0, idx):
if not forbidden[idx - remove]:
return idx - remove
针对索引数组的矢量化方法将是最佳选择,但如果没有这种愚蠢的循环,我什至无法提出正确的方法……在此我不胜感激!< / p>
答案 0 :(得分:0)
这是一种实现方法。不确定是否会比解决方案更好。
第一步,获取所有False
节点的索引:
b = np.where(forbidden == False)[0]
这将返回
array([ 0, 1, 2, 3, 4, 5, 30, 31, 32, 33, 34, 35, 36,
37, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
103, 104, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136], dtype=int64)
然后,在该列表的切片部分再次使用where
和amax
,以使最高索引低于当前索引。然后使用b
上的索引来获得False
数组上最高的forbidden
索引。
>>> index = 15
>>> first_left_false = b[np.amax(np.where(b<index))]
>>> first_left_false
5
该函数可能看起来像这样:
def getCorrectIndex(index, forbidden):
if forbidden[index] == False:
return index
b = np.where(forbidden == False)[0]
res = b[np.amax(np.where(b<index))]
return res
或者,如果您要预先计算b
数组,可以将其略微缩短:
def getCorrectIndex(index, b, forbidden):
if forbidden[index] == False:
return index
else:
return b[np.amax(np.where(b<index))]
答案 1 :(得分:0)
您可以使用np.maximum.accumulate
将布尔数组转换为以前允许的最新索引,然后只需查找第idx
个元素
首先创建一个索引数组,将禁止的位置设置为0。accumulate
返回函数的滚动应用,在这种情况下为maximum
,并且maximum
与{{1 }},它应用于两个数组,返回元素级的max数组。
max
改为右移
将禁止位置设置为任何大于或等于数组长度的值,并在反向查找数组上使用lookup = np.arange(len(forbidden))
lookup[forbidden] = 0
lookup = np.maximum.accumulate(lookup)
lookup[13]
# 5
lookup[5]
# 5
lookup[149]
# 136
。这基本上与上面的左移方法相同。
np.minimum.accumulate