Ruby on rails 基于重复项求二维数组元素和的最简单方法?
假设我有一个2D数组。可能是这样的:Ruby on rails 基于重复项求二维数组元素和的最简单方法?,ruby-on-rails,arrays,ruby,Ruby On Rails,Arrays,Ruby,假设我有一个2D数组。可能是这样的: data = [['oct 1', 4], ['oct 2', 5], ['oct 3', 9], ['oct 1', 2]] 我想从中得到一个新的数组,它删除了重复的值(如10月1日),但对相应的值求和 因此,我最终会: data = (['oct 1', 6], ['oct 2', 5], ['oct 3', 9]) 我可以想出一些方法来做到这一点,但它们似乎效率很低,通常总有一些疯狂的ruby代码可以在几行内完成任何事情,有什么建议吗 尝试使用in
data = [['oct 1', 4], ['oct 2', 5], ['oct 3', 9], ['oct 1', 2]]
我想从中得到一个新的数组,它删除了重复的值(如10月1日),但对相应的值求和
因此,我最终会:
data = (['oct 1', 6], ['oct 2', 5], ['oct 3', 9])
我可以想出一些方法来做到这一点,但它们似乎效率很低,通常总有一些疯狂的ruby代码可以在几行内完成任何事情,有什么建议吗 尝试使用
inject
方法执行以下操作:
data = [["oct 1", 4], ["oct 2", 5], ["oct 3", 9], ["oct 1", 2]]
data.inject({}) { |sum, (n, t)| sum[n] ||= 0; sum[n] += t; sum }.to_a
=> [["oct 1", 6], ["oct 2", 5], ["oct 3", 9]]
这里有几种方法可以做到这一点,我的偏好是第一种 使用计数哈希 代码 请参见,特别是对默认值的讨论 范例 解释
enum
的第一个值传递给块,并使用消歧和并行赋值计算块变量的值
现在,
enum
的其余三个值被传递到块并执行块计算
(date, val), h = enum.next
#=> [["oct 2", 5], {"oct 1"=>4}]
h[date] += val
#=> 5 (the default value of `0` is again used)
h #=> {"oct 1"=>4, "oct 2"=>5}
(date, val), h = enum.next
#=> [["oct 3", 9], {"oct 1"=>4, "oct 2"=>5}]
h[date] += val
#=> 9 (the default value of `0` is again used)
h #=> {"oct 1"=>4, "oct 2"=>5, "oct 3"=>9}
(date, val), h = enum.next
#=> [["oct 1", 2], {"oct 1"=>4, "oct 2"=>5, "oct 3"=>9}]
h[date] += val
#=> 6
h #=> {"oct 1"=>6, "oct 2"=>5, "oct 3"=>9}
a = vals.map(&:last)
#=> [4, 2]
t = a.reduce(:+)
#=> 6
在上一次计算中,没有使用默认值,因为哈希h
已经有一个键“oct 1”
:
最后,
h.to_a
#=> [["oct 1", 6], ["oct 2", 5], ["oct 3", 9]]
使用
代码
范例
解释
步骤如下:
h = data.group_by(&:first)
#=> {"oct 1"=>[["oct 1", 4], ["oct 1", 2]],
# "oct 2"=>[["oct 2", 5]], "oct 3"=>[["oct 3", 9]]}
h
的第一个键值对被传递到块:
date, vals = h.first
#=> ["oct 1", [["oct 1", 4], ["oct 1", 2]]]
date
#=> "oct 1"
vals
#=> [["oct 1", 4], ["oct 1", 2]]
并进行了分块计算
(date, val), h = enum.next
#=> [["oct 2", 5], {"oct 1"=>4}]
h[date] += val
#=> 5 (the default value of `0` is again used)
h #=> {"oct 1"=>4, "oct 2"=>5}
(date, val), h = enum.next
#=> [["oct 3", 9], {"oct 1"=>4, "oct 2"=>5}]
h[date] += val
#=> 9 (the default value of `0` is again used)
h #=> {"oct 1"=>4, "oct 2"=>5, "oct 3"=>9}
(date, val), h = enum.next
#=> [["oct 1", 2], {"oct 1"=>4, "oct 2"=>5, "oct 3"=>9}]
h[date] += val
#=> 6
h #=> {"oct 1"=>6, "oct 2"=>5, "oct 3"=>9}
a = vals.map(&:last)
#=> [4, 2]
t = a.reduce(:+)
#=> 6
因此,h
的第一个键值对被映射到
[date, t]
#=> ["oct 1", 6]
其余的计算结果与此类似。我们希望看到您尝试解决此问题。如果没有这些努力的证据,看起来你希望我们做你应该做的工作。请阅读“”和“”。谢谢,回答得很好。至于我的代码格式,我是这个网站的新手,所以我认为只要一个伪实现就可以了,我的错!关于如何将其推广到例如4D阵列的任何提示?这将取决于阵列的外观。例如,相同的密钥是否会出现在不同的“级别”?最好单独提出一个问题(举个例子)。
h.to_a
#=> [["oct 1", 6], ["oct 2", 5], ["oct 3", 9]]
def combine(data)
data.group_by(&:first).map { |date, vals| [date, vals.map(&:last).reduce(:+)] }
end
combine data
#=> [["oct 1", 6], ["oct 2", 5], ["oct 3", 9]]
h = data.group_by(&:first)
#=> {"oct 1"=>[["oct 1", 4], ["oct 1", 2]],
# "oct 2"=>[["oct 2", 5]], "oct 3"=>[["oct 3", 9]]}
date, vals = h.first
#=> ["oct 1", [["oct 1", 4], ["oct 1", 2]]]
date
#=> "oct 1"
vals
#=> [["oct 1", 4], ["oct 1", 2]]
a = vals.map(&:last)
#=> [4, 2]
t = a.reduce(:+)
#=> 6
[date, t]
#=> ["oct 1", 6]