用于Ruby的填充arrays方法

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

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] 

但是当我没有为“c”输入值时崩溃了

 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上看到了其他填充方法,但它们似乎没有像作者那样按预期工作。 所以,我决定自己动手。

它被杀死了,因为你正在进入无限循环。 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"] 

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

你知道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)> 

无论你想要什么,你都可以填充arrays。 这是一个很酷的实现。 试试看。

在您的控制台中阅读:

 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] 

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"] 

问题是nil被评估为false,因此当[b-1]包含nil时,[b-1]永远不会为真…所以你永远循环直到你失去记忆。

更好…

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

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

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

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

要在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(...)) 。 嗯好吧。 🙂