One liner to limit Array of Words to less than N number of characters in Ruby?
What's the simplest way to limit an array of words such that the resulting array, when the words are joined, is less than 40 characters? Something that acts like this:
words = ["ruby", "rails", "jquery", "javascript", "html"]
words.join.length #=> 29
words.join(", ").length #=> 37
words = ["ruby", "rails", "jquery", "javascript", "html", "css", "api"]
words.join.length #=> 35
words.join(", ").length #=> 47
words.chunk(:max_chars => 40) #=> ["ruby", "rail开发者_JAVA技巧s", "jquery", "javascript", "html"]
Update
Got this so far:
def chop(array, separator = "", max = 40)
result = []
array.each do |word|
break if (result.join(separator).length + word.length > max)
result << word
result
end
result
end
Too bad there is a fencepost condition, otherwise this would be a much cleaner code with the take_while
method
def chop(array, separator = "", max_size = 40)
so_far = 0
sep = separator.size
array.take_while{|word| (so_far += word.size + sep) <= max_size + sep }
end
It checks it is less or equals than max_size + sep
to compensate we are adding a separator to every word, even though the last one doesn't need it.
Here's a fun way, you need active support:
require 'active_support'
class Array
def chunk(sep = "", max = 40)
self.inject([]){|m,n| (m+[n]).sum(&:size)+sep.size*m.size-1<max ? m<<n : m}
end
end
Now:
["ruby", "rails", "jquery", "javascript", "html", "css", "api"].chunk(", ") #=> ["ruby", "rails", "jquery", "javascript", "html"]
A slight variation on yours:
result = input.inject([]){|r,word|r<<word if r*separator+word.length < max}
def chop(arr, sep = "", max = 40)
max += sep.size
arr.take_while{|x| (max -= x.size + sep.size) >= 0 }
end
精彩评论