具有重复索引的数组的总和
Sum of arrays with repeated indices
如何通过索引将一个数字数组添加到另一个数组?特别是对于重复索引。那样
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) 可以是数百万项,我需要快速 'add' 动词。
更新
解决方案(感谢 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
简述:
- 首先对索引数组具有相同值的更新数组(在您的 post、
y
¹ 中)进行分组,然后取每组的总和
- 使用 the adverb key (
/.
) 以总和 (+/
) 作为其动词参数来完成此操作,派生一个二元动词,其参数为左侧的 idx
和右边的更新数组(你的y
,我的updat
)。
- 获取索引数组的核心 (
~.
)
- Select 来自您的值数组的这些(唯一)索引(您的
x
,我的 data
)
- 根据定义,这将与我们在 (1.) 中计算的累积和具有相同的长度
- 将这些添加到累计总和
- 现在您有了对数据的最终更新;
updat
和 idx
具有相同的长度,因此您只需使用 }
将它们合并到您的值数组中,就像您在代码中所做的那样
由于我们保持更新数组较小(永远不会大于其原始长度),这在较大的输入上应该有不错的性能,尽管我没有 运行 任何测试。唯一的性能缺点是 idx
的 nub 的双重计算(一次显式使用 ~.
,一次隐式使用 /.
),尽管由于您的值是整数,这应该相对便宜;就性能而言,这是 J 的强项之一。
¹ 我意识到重命名数组会使这个答案比需要的更冗长。但是,由于您将主数据命名为 x
而不是 y
(这是约定),如果我只是保留您的命名约定,那么当我调用 cumIdx
时,定义内的名词与定义外的名词具有相反的含义,我认为这会引起更大的混淆。因此,最好将“原始数据”放在右边(y
),将“control data”放在左边(x
)。
您还可以考虑将特殊名称 x
、y
、u
、v
、m
和 n
的使用限制在它们已经通过调用显式定义被隐式定义;绝对不要改变他们的名字类别。
此方法也使用密钥 (/.
),但其方法更加简单。
它可能会使用更多 space,特别是对于比 Dan Bron 的大更新。
addByIdx=: {{ (m , i.@# y) +//. x,y }}
updat idx addByIdx data
13 8 3 4
如何通过索引将一个数字数组添加到另一个数组?特别是对于重复索引。那样
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) 可以是数百万项,我需要快速 'add' 动词。
更新
解决方案(感谢 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
简述:
- 首先对索引数组具有相同值的更新数组(在您的 post、
y
¹ 中)进行分组,然后取每组的总和- 使用 the adverb key (
/.
) 以总和 (+/
) 作为其动词参数来完成此操作,派生一个二元动词,其参数为左侧的idx
和右边的更新数组(你的y
,我的updat
)。
- 使用 the adverb key (
- 获取索引数组的核心 (
~.
) - Select 来自您的值数组的这些(唯一)索引(您的
x
,我的data
)- 根据定义,这将与我们在 (1.) 中计算的累积和具有相同的长度
- 将这些添加到累计总和
- 现在您有了对数据的最终更新;
updat
和idx
具有相同的长度,因此您只需使用}
将它们合并到您的值数组中,就像您在代码中所做的那样
由于我们保持更新数组较小(永远不会大于其原始长度),这在较大的输入上应该有不错的性能,尽管我没有 运行 任何测试。唯一的性能缺点是 idx
的 nub 的双重计算(一次显式使用 ~.
,一次隐式使用 /.
),尽管由于您的值是整数,这应该相对便宜;就性能而言,这是 J 的强项之一。
¹ 我意识到重命名数组会使这个答案比需要的更冗长。但是,由于您将主数据命名为 x
而不是 y
(这是约定),如果我只是保留您的命名约定,那么当我调用 cumIdx
时,定义内的名词与定义外的名词具有相反的含义,我认为这会引起更大的混淆。因此,最好将“原始数据”放在右边(y
),将“control data”放在左边(x
)。
您还可以考虑将特殊名称 x
、y
、u
、v
、m
和 n
的使用限制在它们已经通过调用显式定义被隐式定义;绝对不要改变他们的名字类别。
此方法也使用密钥 (/.
),但其方法更加简单。
它可能会使用更多 space,特别是对于比 Dan Bron 的大更新。
addByIdx=: {{ (m , i.@# y) +//. x,y }}
updat idx addByIdx data
13 8 3 4