【问题标题】:Method for padding an array in Ruby在 Ruby 中填充数组的方法
【发布时间】:2014-09-28 11:29:20
【问题描述】:

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

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

【问题讨论】:

    标签: ruby arrays padding


    【解决方案1】:

    你知道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,2,3].padding(10, "YES") 代表OP 的问题#fill => [1, 2, 3].fill('YES', 3...10) 其中 3 可以替换为Array#length
    • @Nishu 没有异议! :-)
    • 这个很全面。非常感谢您的回答!
    【解决方案2】:

    它被杀死了,因为你进入了无限循环。 until a[b-1] 不会完成,因为当你在数组中添加 nils 时,你会得到:

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

    经过几次迭代,a[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"]
    

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

    【讨论】:

    • 感谢您指出这一点!我完全忘记了 nil 与生俱来的虚假性。
    【解决方案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"]
    

    【讨论】:

      【解决方案4】:

      问题在于 nil 被评估为假,因此当 a[b-1] 包含 nil 时,until a[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
      

      【讨论】:

        【解决方案5】:

        要专门在 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(...)) 会更好。嗯嗯。 :)

        【讨论】:

          猜你喜欢
          • 2010-09-16
          • 1970-01-01
          • 2014-08-12
          • 2011-06-03
          • 2020-09-01
          • 2021-06-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多