将数组填充到特定大小

17

可能有一种更高效、更符合Ruby风格的方法来完成这个任务:

# Pad array to size n by adding x's. Don't do anything if n <= a.length.
def padleft(a, n, x)
  return a if n <= a.length
  return padleft([x] + a, n, x)
end

你有什么建议?

7个回答

26

由于我误解了问题,我的答案以前是从右侧填充的,但问题要求从左侧填充。我已经做了相应的更正。这是由于命名约定。 ljustrjustString 的内置方法,我将该约定扩展到了 Array,但在问题术语中,分别对应于 padrightpadleft

破坏性方法

def padleft!(a, n, x)
  a.insert(0, *Array.new([0, n-a.length].max, x))
end
def padright!(a, n, x)
  a.fill(x, a.length...n)
end

更自然的方式是将其定义在Array类上:

class Array
  def rjust!(n, x); insert(0, *Array.new([0, n-length].max, x)) end
  def ljust!(n, x); fill(x, length...n) end
end

非破坏性方法

def padleft(a, n, x)
  Array.new([0, n-a.length].max, x)+a
end
def padright(a, n, x)
  a.dup.fill(x, a.length...n)
end
或者
class Array
  def rjust(n, x); Array.new([0, n-length].max, x)+self end
  def ljust(n, x); dup.fill(x, length...n) end
end

注意:n 是所需索引中最大的一个,而不是所需数组的长度。 - Raphael

5

FWIW:

def rpad(item, padding, num)
  Array(item).fill padding, Array(item).size, num
end
# rpad "initialize value(s)", 0, 3
# => ["initialize value(s)", 0, 0, 0]

4

使用 10 作为填充长度,'x' 作为填充值,可以进行右侧填充:

>> asdf = %w[0 1 2 3 ] #=> ["0", "1", "2", "3"]
>> asdf += (asdf.size < 10) ? ['x'] * (10 - asdf.size) : [] #=> ["0", "1", "2", "3", "x", "x", "x", "x", "x", "x"]

或者

>> asdf = (asdf.size < 10) ? ['x'] * (10 - asdf.size) + asdf : asdf #=> ["x", "x", "x", "x", "x", "x", "0", "1", "2", "3"]

填充到左侧

如果在数组上打补丁十分有意义:

class Array
  def pad_right(s, char=nil)
    self + [char] * (s - size) if (size < s)
  end

  def pad_left(s, char=nil)
    (size < s) ? [char] * (s - size) + self : self
  end
end

%w[1 2 3].pad_right(5, 'x') # => ["1", "2", "3", "x", "x"]
%w[1 2 3].pad_left(5, 'x') # => ["x", "x", "1", "2", "3"]

2
使用 * 运算符来重复一个列表。
# Pad array to size n by adding x's. Don't do anything if n <= a.length.
def padleft(a, n, x)
  return a if n <= a.length
  return [x] * (n - a.length) + a
end

1

这里有另一个有趣的一行代码可以做到:

(非破坏性)

def padleft(a, n, x)
  a.dup.reverse.fill(x, a.length..n-1).reverse
end

(破坏性的)

def padleft(a, n, x)
  a.reverse.fill(x, a.length..n-1).reverse
end

只是好奇,为什么会有负评?这个解决方案不再正确吗? - Topher Fangio
1
抱歉,我本意是在给出负面评价时写一个简短的摘要,但是有其他事情突然冒了出来。当处理常用字符串函数时,反转2倍不应该是正确的解决方案。这样的代码是开源软件中大多数减速的根源。当核心字符串库中有这样的代码时,会有人使用单个重新分配和循环设置填充字符来重写它,并在博客上吹嘘。 - nurettin
2
虽然这可能不是最有效率的代码,但它仍然有吸引力。在编写 Ruby 代码时,我们通常更加注重诗意而非实用性。只要它没有在大规模循环中执行,我认为就可以使用它。 - superluminary

1
也许更加“Ruby风格” ;)
# Pad array to size n by adding x's. Don't do anything if n <= a.length.
def padleft(a, n, x)
  (n - a.size).times.inject(a) do |array, i|
    array << x
  end
end

-1
如果您正在使用Rails并且想要右侧的填充:
[1,2,3,4,5,6].in_groups_of(4)
=> [[1, 2, 3, 4], [5, 6, nil, nil]]

这与回答问题毫无关系,但是在访问此页面后,它是我最终所需的东西。希望能对某人有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接