我有两个(或更多)数组,每个数组有 12 个整数(对应于每个月的值)。我想要的只是将它们加在一起,这样我就得到了一个包含每个月求和值的数组。这是一个具有三个值的示例: [1,2,3] 和 [4,5,6] => [5,7,9]
我能想到的最好的办法是:
[[1,2,3],[4,5,6]].transpose.map{|arr| arr.inject{|sum, element| sum+element}} #=> [5,7,9]
有更好的方法吗?这似乎是一件很基本的事情。
这是 Anurag 建议的
transpose
版本:
[[1,2,3], [4,5,6]].transpose.map {|x| x.reduce(:+)}
这适用于任意数量的组件数组。
reduce
和 inject
是同义词,但 reduce
在我看来更清楚地传达了代码的意图......
现在我们可以在2.4中使用sum
nums = [[1, 2, 3], [4, 5, 6]]
nums.transpose.map(&:sum) #=> [5, 7, 9]
为了更清晰的语法(不是最快的),您可以使用
Vector
:
require 'matrix'
Vector[1,2,3] + Vector[4,5,6]
=> Vector[5, 7, 9]
对于多个向量,你可以这样做:
arr = [ Vector[1,2,3], Vector[4,5,6], Vector[7,8,9] ]
arr.inject(&:+)
=> Vector[12, 15, 18]
如果您希望将数组加载到向量中并求和:
arrays = [ [1,2,3], [4,5,6], [7,8,9] ]
arrays.map { |a| Vector[*a] }.inject(:+)
=> Vector[12, 15, 18]
这是我对代码高尔夫的尝试:
// ruby 1.9 syntax, too bad they didn't add a sum() function afaik
[1,2,3].zip([4,5,6]).map {|a| a.inject(:+)} # [5,7,9]
zip
返回 [1,4]
、[2,5]
、[3,6]
,map 对每个子数组求和。
我谦虚地认为我看到的其他答案非常复杂,以至于会让代码审查者感到困惑。您需要添加解释性注释,这只会增加所需的文本量。
这个怎么样:
a_arr = [1,2,3]
b_arr = [4,5,6]
(0..2).map{ |i| a_arr[i] + b_arr[i] }
稍微不同的解决方案:(这样你就不会硬编码“2”)
a_arr = [1,2,3]
b_arr = [4,5,6]
c_arr = []
a_arr.each_index { |i| c_arr[i] = a_arr[i] + b_arr[i] }
最后,从数学上来说,这与以下问题是相同的:
[[1,2,3],[4,5,6]].transpose.map{|a| a.sum} #=> [5,7,9]
@FriendFX,您对@user2061694 的回答是正确的。它只适用于我的 Rails 环境。如果进行以下更改,您可以使其在纯 Ruby 中运行...
在IRB
[[0, 0, 0], [2, 2, 1], [1,3,4]].transpose.map {|a| a.inject(:+)}
=> [3, 5, 5]
[[1,2,3],[4,5,6]].transpose.map {|a| a.inject(:+)}
=> [5, 7, 9]
对于:
a = [1,2,3]
b = [4,5,6]
您可以
zip
然后使用 reduce
:
p a.zip(b).map{|v| v.reduce(:+) }
#=> [5, 7, 9]
或者,如果您确定数组
a
和 b
的长度始终相等:
p a.map.with_index { |v, i| v + b[i] }
#=> [5, 7, 9]
这可能不是最好的答案,但它确实有效。
array_one = [1,2,3]
array_two = [4,5,6]
x = 0
array_three = []
while x < array_one.length
array_three[x] = array_one[x] + array_two[x]
x += 1
end
=>[5,7,9]
这可能比其他答案有更多的代码行,但它仍然是一个答案
只是为了好玩,我对一些可能的解决方案进行了基准测试
# plain-ole
a[0] += b[0]
a[1] += b[1]
a[2] += b[2]
a
# each_index
a.each_index { |i| a[i] += b[i] }
#zip-sum
a.zip(b).map(&:sum)
# transpose-sum
[a, b].transpose.map(&:sum)
#map
a.map.with_index { |v, i| v + b[i] }
# zip-reduce
a.zip(b).map { _1.reduce(&:+) }
# transpose-reduce
[a, b].transpose.map { _1.reduce(&:+) }
# vector-declared
Vector[1, 2, 3] + Vector[4, 5, 6]
# vector
Vector.elements(a) + Vector.elements(b)
使用 Benchmark 并运行各 1,000,000 次,得到以下结果。
Rehearsal ------------------------------------------------------
plain-ole 0.217787 0.000722 0.218509 ( 0.218544)
each_index 0.431834 0.001533 0.433367 ( 0.433421)
zip-sum 0.576384 0.002875 0.579259 ( 0.579365)
transpose-sum 0.588562 0.002788 0.591350 ( 0.591382)
map 0.774294 0.002759 0.777053 ( 0.777108)
zip-reduce 1.217026 0.005008 1.222034 ( 1.222105)
transpose-reduce 1.244968 0.005115 1.250083 ( 1.250596)
vector-initialized 1.691190 0.004128 1.695318 ( 1.695422)
vector 1.972912 0.005582 1.978494 ( 1.978689)
--------------------------------------------- total: 8.745467sec
user system total real
plain-ole 0.215911 0.000831 0.216742 ( 0.216781)
each_index 0.430009 0.001125 0.431134 ( 0.431200)
zip-sum 0.567621 0.002756 0.570377 ( 0.570465)
transpose-sum 0.589709 0.002606 0.592315 ( 0.592342)
map 0.769459 0.002611 0.772070 ( 0.772167)
zip-reduce 1.209870 0.004881 1.214751 ( 1.214985)
transpose-reduce 1.230031 0.004926 1.234957 ( 1.235065)
vector-initialized 1.687652 0.003992 1.691644 ( 1.691750)
vector 1.974240 0.005038 1.979278 ( 1.979393)