Pad an array to be a certain size
There's probably a more efficient and more Rub开发者_Go百科y-ish way to do this:
# 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
What would you suggest?
Edited due to my misunderstanding of the question. Pervious version of my answer padded from the right side, but the question was asking to do it from the left side. I corrected it accordingly. This is due to naming convention. ljust
, rjust
are builtin methods for String
, and I extended that convention to Array
, but that corresponds to padright
and padleft
, respectively, in the terminology of the question.
Destructive methods
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
It would be more natural to have it defined on Array
class:
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
Non-destructive methods
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
or
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
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]
Using 10
for the length to pad to, and 'x'
to be what you're padding to, this pads right:
>> 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"]
or
>> asdf = (asdf.size < 10) ? ['x'] * (10 - asdf.size) + asdf : asdf #=> ["x", "x", "x", "x", "x", "x", "0", "1", "2", "3"]
to padleft
If it makes sense to you to monkey-patch Array:
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"]
Using the * operator to repeat a list.
# 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
Perhaps more Rubyish ;)
# 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
Here's another fun one-liner to do it:
(non-destructive)
def padleft(a, n, x)
a.dup.reverse.fill(x, a.length..n-1).reverse
end
(destructive)
def padleft(a, n, x)
a.reverse.fill(x, a.length..n-1).reverse
end
If you're using Rails and want the padding on the right:
[1,2,3,4,5,6].in_groups_of(4)
=> [[1, 2, 3, 4], [5, 6, nil, nil]]
This doesn't come anywhere near answering the question but it's what I ended up needing after visiting this page. Hope it helps someone.
精彩评论