如何通过索引将一个数字数组添加到另一个数组?特别是对于重复索引。就这样
x
1 2 3 4
idx
0 1 0
y
5 6 7
] x add idx;y NB. (1 + 5 + 7) , (2 + 6) , 3 , 4
13 8 3 4
所有名词(x、idx、y)都可以是数百万个项目,我需要快速“添加”动词。
更新
解决方案(感谢 Dan Bron):
cumIdx =: 1 : 0
:
'i z' =. y
n =. ~. i
x n}~ (n{x) + i u//. z
)
(1 2 3 4) + cumIdx (0 1 0);(5 6 7)
13 8 3 4
最佳答案
现在,在“完成它”模式下的简短回答:
data =. 1 2 3 4
idx =. 0 1 0
updat =. 5 6 7
cumIdx =: adverb define
:
n =. ~. m
y n}~ (n{y) + m +//. x
)
updat idx cumIdx data NB. 13 8 3 4
简而言之:
- 首先对索引数组具有相同值的更新数组(在您的帖子中,
y
¹)进行分组,然后取每组的总和- 使用 the adverb key 完成此操作(
/.
) 以 sum (+/
) 作为其动词参数,派生一个二元动词,其参数为左边的idx
和更新右边的数组(你的y
,我的updat
)。
- 使用 the adverb key 完成此操作(
- 获取索引数组的核心 (
~.
) - 从您的值数组中选择这些(唯一的)索引(您的
x
,我的data
)- 根据定义,这将与我们在 (1.) 中计算的累积和具有相同的长度。
- 将这些添加到累计总和
- 现在您有了对数据的最终更新;
updat
和idx
具有相同的长度,因此您只需使用}
将它们合并到您的值数组中,就像您在代码中所做的那样
由于我们保持更新数组较小(永远不会大于其原始长度),因此这在较大的输入上应该有不错的性能,尽管我没有运行任何测试。唯一的性能缺陷是对 idx
的 nub 进行了双重计算(一次显式地使用 ~.
并且一次隐式地使用 /.
),尽管因为你的值是整数,这应该比较便宜;在性能方面,这是 J 的强项之一。
¹ 我意识到重命名你的数组会使这个答案比它需要的更冗长。但是,由于您将主数据命名为 x
而不是 y
(这是约定),如果我只是保留您的命名约定,那么当我调用 cumIdx
,定义内的名词名称将与定义外的名词具有相反的含义,我认为这会引起更大的混淆。因此,最好将“原始数据”放在右边 (y
),将“control data”放在左边 (x
)。
您还可以考虑限制使用特殊名称 x
、y
、u
、v
,m
和 n
到它们已经通过调用显式定义隐式定义的地方;绝对不要更改他们的名称类。
关于j - 具有重复索引的数组的总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69101709/