【问题标题】:Sum of arrays with repeated indices具有重复索引的数组的总和
【发布时间】:2021-09-08 10:52:31
【问题描述】:

如何通过索引将一个数字数组添加到另一个数组?尤其是重复索引。就这样

   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

【问题讨论】:

    标签: j


    【解决方案1】:

    现在,在“完成”模式下做一个简短的回答:

    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
    

    简而言之:

    1. 首先对索引数组具有相同值的更新数组(在您的帖子中,y¹)进行分组,然后取每个组的总和
      1. 使用 the adverb key (/.) 和 sum (+/) 作为其口头参数,派生一个二元动词,其参数为左侧的 idx 和更新数组(您的 y,我的updat) 在右侧。
    2. 获取索引数组的小块 (~.)
    3. 从你的值数组中选择这些(唯一的)索引(你的x,我的data
      1. 根据定义,这将与我们在 (1) 中计算的累积总和具有相同的长度。
    4. 将这些添加到累积总和中
    5. 现在您已经对数据进行了最终更新; updatidx 具有相同的长度,因此您只需使用 } 将它们合并到您的值数组中,就像您在代码中所做的那样

    由于我们保持更新数组较小(从不大于其原始长度),这应该在较大的输入上具有不错的性能,尽管我没有运行任何测试。唯一的性能缺点是idx 的小块的双重计算(一次显式使用~.,一次隐式使用/.),但由于您的值是整数,这应该相对便宜;就性能而言,这是 J 的强项之一。


    ¹ 我意识到重命名你的数组会使这个答案比它需要的更冗长。但是,由于您将主要数据命名为 x 而不是 y(这是约定),如果我只是保持您的命名约定,那么当我调用 cumIdx 时,定义中的名词名称将与定义之外的含义相反,我认为这会引起更大的混乱。因此,最好将“主要数据”保留在右侧 (y),将“control data”保留在左侧 (x)。

    您还可以考虑限制使用特殊名称 x,y,u,v,mn 到它们已经通过调用显式定义隐式定义的位置;绝对永远不要改变他们的名字。

    【讨论】:

    • 谢谢!我完全忘记了“/”。为问题添加解决方案
    • @JacobJacob 当然,没问题;绝对/. 是 J 中的一颗宝石。作为仅供参考,因此没有必要为问题添加解决方案。我们不同于传统的论坛。无论如何,希望再次在J标签中见到你。如果我在附近,我会尽力提供帮助。
    【解决方案2】:

    此方法也使用密钥 (/.),但其方法更简单一些。 与 Dan Bron 相比,它可能会使用更多空间,尤其是用于大型更新。

       addByIdx=: {{ (m , i.@# y) +//. x,y }}
       updat idx addByIdx data
    13 8 3 4
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-08
      相关资源
      最近更新 更多