gpt4 book ai didi

ruby - 数字数组的总和

转载 作者:数据小太阳 更新时间:2023-10-29 07:40:52 25 4
gpt4 key购买 nike

这个问题已经有了答案:
How to sum array of numbers in Ruby?
22答
问:编写一个方法sum,它接受一个数字数组并返回数字的和。
A

def sum(nums)
total = 0

i = 0
while i < nums.count
total += nums[i]

i += 1
end

# return total
total
end

必须有另一种方法来解决这个问题而不用while,对吧?有人知道怎么做吗?
编辑:这不是考试。这是github上为app academy提供的一个实践问题。他们以问答为例。不过,我刚读到好的程序员不喜欢使用while或untile,所以我很好奇是否能学到一些更好的方法来解决这个问题。比如可枚举?(显然,鲁比没有…)
同时,我也很喜欢任何我应该学习的演练或方法。这个问题也是不同的,因为我要求具体的例子使用这些数据。

最佳答案

通常的做法是:

def sum(nums) nums.reduce(&:+) end

它的缩写是这样的:
def sum(nums)  nums.reduce(0) { |total, num| total + num } end

我看到尼尔在我输入这个时发布了一个类似的解决方案,所以我只需要注意 reduceinject是同一个方法的两个名称-ruby有几个类似的别名,这样,使用不同语言的人就可以找到他们要找的东西。他还留下了 &,这在为 reduce/ inject使用命名方法时是可选的,但在其他情况下不是。
解释如下。
在ruby中,通常不使用显式循环( forwhile,等等)。取而代之的是,对要遍历的集合调用方法,并向它们传递一个代码块,以便在每个项上执行。ruby的语法将块放在方法的参数之后,介于 do.. end{.. }之间,因此它看起来像传统的命令式流控制,但它的工作方式不同。
基本的迭代方法是:
[1,2,3].each do |i| puts i end

它调用块 each三次,传递它1,然后传递它2,最后传递它3。 do |i| puts i end是一个块参数,它告诉ruby每次将传递到块中的值放在哪里。
但是 |i|只是丢弃了块调用的返回值(在本例中, each返回的三个 nils)。如果要对这些返回值执行某些操作,则必须调用其他方法。例如, puts返回返回值的数组:
[1,2,3].map do |i| puts i end
#=> [nil, nil, nil]

这在这里不是很有趣,但是如果块返回一些内容,它会变得更有用:
[1,2,3].map do |i| 2*i end  
#=> [2,4,6]

如果希望将结果合并为单个聚合返回值,而不是返回与输入大小相同的数组,则在到达 map时。除了块之外,它还需要一个额外的参数,并且块本身也用一个额外的参数调用。这个额外的参数称为“累加器”。第一次调用块时,它获取最初传递给 reduce的参数,但从那时起,它获取上一次对块的调用的返回值,即每个块调用可以如何将信息传递给下一次。
这使得 reducereduce更通用;实际上,您可以通过传入一个空数组并将块添加到其中来构建 map
[1,2,3].reduce([]) do |a,i| a + [2*i] end 
#=> [2,4,6]

但既然 map已经定义好了,你通常只需要使用它,并且只使用 reduce来做更简单的事情:
[1,2,3].reduce(0) do |s, i| s + 2*i end  
#=> 12

……这就是我们解决你问题的方法。
尼尔和我走了几条捷径。首先,如果一个块只对其参数调用一个方法并返回结果,那么可以通过在方法名前面加上 map来获得一个等价的块。也就是说,这个:
some_array.reduce(x) do |a,b| a.some_method(b) end

可以更简单地重写如下:
some_array.reduce(x, &:some_method)

由于ruby中的 reduce实际上只是编写方法调用 &:的一种更为常见的方法,这意味着您可以通过传入 a + b来累加数字:
[1,2,3].reduce(0, &:+)
#=> 6

接下来, a.+(b)的初始累加器值是可选的;如果不使用它,那么第一次调用块时,它将获取数组的前两个元素。所以你可以不使用 &:+
[1,2,3].reduce(&:+)
#=> 6

最后,在传递不是文本代码块的块时,通常需要 reduce;可以将块转换为proc对象,并将它们存储在变量中,这些变量可以传递给不同的迭代器方法。当传递这样的变量时,通过将 0放在前面,可以指示应该将其解释为块而不是常规参数。
一些方法,包括 &,也会接受一个裸符号(比如 &)并为您创建proc/block,Neil利用了这个事实。但是其他迭代器方法,比如 reduce,并不是这样工作的:
irb(main):001:0> [-1,2,-3].map(:abs)
ArgumentError: wrong number of arguments (1 for 0)
from (irb):1:in `map'
from (irb):1
from /usr/bin/irb:12:in `<main>'

所以我总是使用 :+
irb(main):002:0> [-1,2,-3].map(&:abs)
#=> [1, 2, 3]

ruby有很多好的在线教程。有关map/reduce和相关概念以及如何将其应用于问题解决的更一般的信息,您应该搜索“函数式编程”的介绍,这是因为它处理“函数”(即,可执行代码块,它在ruby中被实现为 map对象)就像数字和字符串一样的值,可以被传递、分配给变量等。

关于ruby - 数字数组的总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22818637/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com