我的代码如下:
a = [435,276,434]
def product(a)
final = 1
for e in a
for p in a[e]
final*=p
end
end
final
end
puts product(a)
我想知道如何迭代这个数组两次,结果是4 * 3 * 5 = 60,2 * 7 * 6 = 85,以及4 * 3 * 4 = 48
我在上面编写了一些代码,我认为这样可以解决这个问题,但Ruby一直在返回错误。
答案 0 :(得分:5)
要考虑几点:
在Ruby中,你基本上不会使用for
循环来迭代事物。 #each
更好。你可以通过一个街区,为你提供各种灵活性和表现力的空间。
此外,你不能 - 通常 - 迭代Integer
。请记住,Integer是一个数值存储,而不是特定的表示,因此它必须依赖于您想要的表示的基础。如果你想要一个字符串字符,每个字符都恰好是数字,那么,猜猜是什么?你想要一个String
,就像这里的seph解决方案一样。或者Array
,这可能会更有意义,因为每个整数都将保持整数,并且不必来回解析。
告诉你什么,让我们构建一个非常酷的方法来完成这个并将其固定到Integer上,并希望展示Ruby的一些很酷的功能。
class Integer
include Enumerable
def each(base = 10, &blk)
front, back = abs.divmod(base)
if front > 0
front.each(base, &blk)
end
yield back
end
end
这个小数字取一个基数和一个块,得到整数的绝对值(因为从技术上讲,减号不是一个数字),然后用divmod分割数字,砍掉最后一个数字。我们将这些碎片存放在前后。我们检查是否有更多的数字,由前面0表示,如果我们以递归方式调用此方法,则使用该块。然后我们只是屈服于后面,将数字发送到块。
由于我们现在已经定义了each
方法,因此我们现在可以自由地添加Enumerable
,这可以为我们带来很多东西!
只要该修改处于有效状态,您的product
方法就会变为:
(如果你想打印60 84 48):a.map {|n| n.reduce(:*)}
(或者如果你想打印241920):a.reduce(:*).reduce(:*)
非常好!
所以,这个完整的解决方案比seph的单行程要长一点,事实上如果我需要实际做一些事我只会to_s
。我的解决方案执行速度更快吗?谁知道?但它肯定更具表现力,这就是你首先使用Ruby的原因。
如果你想解决一个问题,是的,绝对是to_s
。但是如果你希望你的代码能够表达一种关于数字的哲学,那么它们实际上也只是它们的集合 - 而且它们以一种奇怪的集理论方式,让你能够让它成为那样的。而这种根本不需要字符串的方式,他们完全没有勉强的帮助。你可以迭代不同的基础,如果你正在做十六进制或二进制,这是非常有用的,它保留了它们的更多数字本质。
在你和我一起建立的这个世界里,贾马尔,小整数与大男孩一起穿过森林。这太好了。
答案 1 :(得分:4)
您可以将其转换为字符串(.to_s)。然后很容易将每个数字作为char(.chars),将它们转换回整数(.map(&:to_i))并将它们相乘(.reduce(:*))
a = [435,276,434]
a.map {|n| n.to_s.chars.map(&:to_i).reduce(:*) }
=> [60, 84, 48]
答案 2 :(得分:3)
以下是修复代码的一种方法:
a = [435,276,434]
def product(a)
result = [] # Create an empty array that will become [60, 85, 48]
for e in a
final = 1
# Convert the integer e to a string (e.g., "435")
str = e.to_s
# Iterate over each char of the string (e.g., "4", "3" and "5")
str.each_char do |c|
# Convert the character 'c' to an integer (digit) then multiply final by that integer
final *= c.to_i
end
# Append the value of final to the result array
result << final # e.g., when result = [60], result << 85 => [60, 85]
end
result # => [60, 85, 48]
end
product(a) # => [60, 85, 48]
现在让我们看看我们如何改进它。首先,我们可以链接操作并避免使用临时变量str
。此外,你会发现for循环,each
通常比for
更好(特别是因为你可以使用each
的块),所以我也会改变它。虽然我在这,但由于each_char
循环只包含一个语句,我将用括号而不是do/end
编写块。我们现在有:
def product(a)
result = [] # Create an empty array that will become [60, 85, 48]
a.each do |e|
final = 1
e.to_s.each_char {|c| final *= c.to_i}
result << final
end
result
end
当我看到这个时,我想我想将数组a
的每个元素转换为其他元素(其数字的乘积)。这表明使用Array
方法map!
(或其同义词,collect!
),而不是each
。由于a
是方法product
的参数,如果我使用a.map!
,则会更改调用a
的方法中product
的值。这可能也可能不行,但由于我正在返回计算值的数组,因此可能不行,所以我将map!
应用于a
的副本。 (它被称为“浅层”副本,这在这里并不重要,但可以在其他情况下使用。)我们现在有了这个:
def product(a)
result = a.dup
result.map! do |e|
final = 1
e.to_s.each_char {|c| final *= c.to_i}
final
end
result
end
我们不需要上一个result
,因为map!
会返回result
(以及更改result
)。嘿,这也意味着我们可以只使用map
(没有区别)。此外,我们可以链接a.dup
和map
以摆脱result
:
def product(a)
a.dup.map do |e|
final = 1
e.to_s.each_char {|c| final *= c.to_i}
final
end
end
伙计,我们用煤气做饭!接下来,每当您看到计算产品或某事物总和的块时,请考虑inject
(或其同义词,reduce
):
def product(a)
a.dup.map do |e|
e.to_s.each_char.inject(1) {|final, c| final * c.to_i}
end
end
假设a
&lt; 0.该怎么办? (@Leon的回答让我觉得这种可能性。)负面接收者对each
毫无意义,所以如果发生这种情况,让我们提出异常:
def product(a)
raise RuntimeError, "Receiver must be non-negative" if self < 0
a.dup.map do |e|
e.to_s.each_char.inject(1) {|final, c| final * c.to_i}
end
end
你可能想停在这里,但你可以用另一个`inject:
替换map
def product(a)
raise RuntimeError, "Receiver must be non-negative" if self < 0
a.inject([]) {|result, e| result.concat.e.to_s.each_char.inject(1) {|final, c| final * c.to_i}}
end
这里的注入参数是一个名为result
的空数组。请注意,由于我们尚未更改a
,因此我们不再需要dup
。 (我看到@Kingston得到了类似的答案。)如果你愿意,可以写成:
def product(a)
raise RuntimeError, "Receiver must be non-negative" if self < 0
a.inject([]) {|result, e| result << e.to_s.each_char.inject(1) {|final, c| final * c.to_i}; result}
end
但请注意需要将那个讨厌的; result
作为结束。
你可能会认为所有这些“改进”的最终结果太过于令人难以理解,或者作者只是炫耀。这就是我刚认识Ruby时的想法。但是,凭借经验,您会发现它非常自然,读起来像一个句子。它还使调试更容易:从左到右工作,您可以测试链的每个链接,以确保它正常工作。
答案 3 :(得分:0)
a.collect{|x|
result = 1
x.to_s.split('').each{|y| result *= y.to_i}
result
}
答案 4 :(得分:0)
如果意图只是迭代数字,你也可以使用字符串切片方法。
char buf[32];
snprintf(buf, 32, "%d %d", input.Z_pos_Camera_Temperature, input.Z_neg_Camera_Temperature);
或
num = a[0].to_s # "435"
final = num[0,1].to_i * num[1,1].to_i * num[2,1].to_i #4*3*5
对于给定的问题,如果你知道它是一个3位数的数组,那么你可以跳过内循环,解决方案可能是这样的:
final = num[0..1].to_i * num[1..2].to_i * num[2..3].to_i
这个答案仅适用于上述问题。由于它操纵相同的数组,因此它编辑接收器。有关更详细和完整的解决方案,请查看Cary Swoveland的答案。