如何在Ruby的循环迭代中刷新数组?

时间:2017-12-17 07:18:59

标签: arrays ruby

对于给定的数组,我想计算总是留下一个值的产品。例如,对于输入[1, 2, 3, 4],我想要输出[2*3*4, 1*3*4, 1*2*4, 1*2*3],即[24, 12, 8, 6]

def array_product(array)
  arr_lgth=array.length
  array_d=array.dup 
  sum=[]
  itr=0

  while itr<(arr_lgth)
    p itr
    p array

    array[itr]=1
    sum << array.reduce(1,:*); 
    array=array_d

    itr+=1
  end

  return sum
end

array_product([1,2,3,4])

当我跟踪迭代和数组时,我得到以下不明白的结果:

0
[1, 2, 3, 4]
1
[1, 2, 3, 4]
2
[1, 1, 3, 4]
3
[1, 1, 1, 4]

在每个while循环迭代结束时,不应该为数组分配重复值吗?

3 个答案:

答案 0 :(得分:5)

这段代码中有很多内容应该是一个简单的问题。 Ruby的优势之一是能够为这个确切的问题表达一个简单的解决方案。我认为你要做的事情是:

def array_product(array)
  # Convert each index in the array...
  array.each_index.map do |i|
    # ...into a copy of the array with that index set as 1...
    array.each_with_index.map do |a, j|
      i == j ? 1 : a
    end.reduce(1, :*) # ...multiplied together.
  end
end

很少见到传统的for循环,在Ruby中使用类似迭代器的变量,因为Enumerable库中有大量工具使它们大多数过时。

这里的关键是尽可能使用像map这样的工具而不是dup,并且使用索引变量来处理数据。当您需要1:1&#34;映射&#34;时,map功能是关键。将原始数据放入一个相同长度的数组中,您可以决定如何单独处理每个元素。

此代码生成:

array_product([ 1, 2, 3 ])
# => [6, 3, 2]

答案 1 :(得分:3)

基本上你想找到三个数字的每个组合的乘积。

[1,2,3,4].combination(3).map{|c| c.reduce(:*)}

答案 2 :(得分:2)

您的错误是您只复制一次给定的数组。对于第一个索引,然后使用给定的数组,然后设置array=array_d,然后在上设置所有剩余的索引,您正在处理重复的在整个过程中,越来越多地将1写入其中。

解决此问题的最简单方法是在其中使用array=array_d.dup,即只在其中附加.dup。然后你不能一遍又一遍地在同一个数组上工作,而是总是按照你的意愿重置为原始(重复)值。

但是,在计算每个产品之前,只需重复,并使用新的副本来计算产品,这样做会更好。所以改变你的内心部分:

    array_d = array.dup 
    array_d[itr] = 1
    sum << array_d.reduce(:*)

整个方法制作了红宝石:

def array_product(array)
  array.each_index.map do |i|
    dup = array.dup
    dup[i] = 1
    dup.reduce(:*)
  end
end

请注意,您不需要使用reduce初始化1

哦,如果您的阵列没有零,您也可以只计算所有数字的产品,然后将其除以每个数字。那要快得多:

def array_product(array)
  p = array.reduce(:*)
  array.map { |x| p / x }
end