在Ruby中填充数组的方法

时间:2014-08-05 17:36:09

标签: ruby arrays padding

这就是我现在拥有的东西,它有点工作:

def padding(a, b, c=nil)
  until a[b-1]
    a << c
  end
end

这就是它的工作原理:

a=[1,2,3]
padding(a,10,"YES")
=>[1, 2, 3, "YES", "YES", "YES", "YES", "YES", "YES", "YES"]

a[1,2,3]
padding(a,10,1)
=>[1, 2, 3, 1, 1, 1, 1, 1, 1, 1]

但是当我没有为&#34; c&#34;

输入值时它会崩溃
a=[1,2,3]
padding(a,10)
Killed

我应该如何追加它以避免崩溃? 另外,您如何建议更改此方法以使用它:

[1,2,3].padding(10)
=>[1,2,3,nil,nil,nil,nil,nil,nil,nil]
[1,2,3].padding(10, "YES")
=>[1, 2, 3, "YES", "YES", "YES", "YES", "YES", "YES", "YES"]

我在SO上看过其他填充方法,但它们似乎并没有像作者那样按预期工作。所以,我决定自己动手。

5 个答案:

答案 0 :(得分:13)

您知道Array#fill方法: -

确实如此,你究竟在寻找什么。如果它存在,为什么你想要自己的。

arup@linux-wzza:~> pry
[1] pry(main)> a=[1,2,3]
=> [1, 2, 3]
[2] pry(main)> a.fill('YES', 3...10)
=> [1, 2, 3, "YES", "YES", "YES", "YES", "YES", "YES", "YES"]
[3] pry(main)>

您可以填写您的数组,无论您想要什么。这是一个很酷的实现。试一试。

在你的控制台中阅读:

arup@linux-wzza:~> ri Array#fill

= Array#fill

(from ruby site)
------------------------------------------------------------------------------
  ary.fill(obj)                                 -> ary
  ary.fill(obj, start [, length])               -> ary
  ary.fill(obj, range )                         -> ary
  ary.fill { |index| block }                    -> ary
  ary.fill(start [, length] ) { |index| block } -> ary
  ary.fill(range) { |index| block }             -> ary

------------------------------------------------------------------------------

The first three forms set the selected elements of self (which may be the
entire array) to obj.

A start of nil is equivalent to zero.

A length of nil is equivalent to the length of the array.

The last three forms fill the array with the value of the given block, which
is passed the absolute index of each element to be filled.

Negative values of start count from the end of the array, where -1 is the last
element.

  a = [ "a", "b", "c", "d" ]
  a.fill("x")              #=> ["x", "x", "x", "x"]
  a.fill("z", 2, 2)        #=> ["x", "x", "z", "z"]
  a.fill("y", 0..1)        #=> ["y", "y", "z", "z"]
  a.fill { |i| i*i }       #=> [0, 1, 4, 9]
  a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]

答案 1 :(得分:5)

它被杀死了,因为你正在进入无限循环。 until a[b-1]将无法完成,因为当您向数组添加nils时,您将获得:

a == [1, 2, 3, nil, nil, nil, nil, nil, nil, nil]

经过几次迭代后,[b-1]将为nil,这是假的。直到永远不会停止。

关于第二个问题,扩展现有的Array类很容易:

class Array
  def padding(i, value=nil)
    (i - length).times { self << value }
    self
  end
end

按预期结果:

[1,2,3].padding(10)
#=> [1, 2, 3, nil, nil, nil, nil, nil, nil, nil]
[1,2,3].padding(10, "YES")
#=> [1, 2, 3, "YES", "YES", "YES", "YES", "YES", "YES", "YES"]

请注意关于修改现有数组的方法(因为Ruby约定应该被称为padding!):

a = [1,2,3]
#=> [1, 2, 3]
a.padding(10, "YES")
#=> [1, 2, 3, "YES", "YES", "YES", "YES", "YES", "YES", "YES"]
a
#=> [1, 2, 3, "YES", "YES", "YES", "YES", "YES", "YES", "YES"]

但是当然你可以轻松创建不修改的方法版本。我假设您要修改数组,因为您的原始方法是这样做的。

答案 2 :(得分:3)

Arup已经钉了它,但这是另一种方式:

def padding(a,b,c)
  [*a, *[c]*b]
end

a=[1,2,3]
padding(a,5,"YES")
  #=> [1, 2, 3, "YES", "YES", "YES", "YES", "YES"]

答案 3 :(得分:2)

问题是nil被评估为false,所以当[b-1]包含nil时,until a[b-1]永远不会为真...所以你永远循环直到你的内存不足。

最好做...

def padding(a, b, c=nil)
  until a.size >= b
    a << c
  end
end

EDIT (是的,Arup的答案非常简洁)

你可以做一个单行,这个更紧凑......

def padding(a, b, c=nil)
  a << c until a.size >= b
end

答案 4 :(得分:0)

在Array上专门实现padding方法:

module Padding
  refine Array do
    def padding(new_length, element=nil)
      if self.size < new_length
        self.concat(Array.new(new_length - self.size, element))
      end
    end
  end
end

using Padding
puts [1,2,3].padding(10).inspect
# => [1, 2, 3, nil, nil, nil, nil, nil, nil, nil]
puts [1,2,3].padding(10, "YES").inspect
# => [1, 2, 3, "YES", "YES", "YES", "YES", "YES", "YES", "YES"]

编辑:忘记了Array#fill。 Arup的答案很酷(即使你需要说fill(3, 7)而不是fill(-1, 10),因为后者给出了错误的结果)。最好使用它而不是concat(Array.new(...))。嗯好吧。 :)