¿Cuál es la mejor manera de cortar una cuerda en trozos de una longitud determinada en Ruby?
string chunking (5)
He estado buscando una manera elegante y eficiente de dividir una cadena en subcadenas de una longitud determinada en Ruby.
Hasta ahora, lo mejor que se me ocurrió fue esto:
def chunk(string, size)
(0..(string.length-1)/size).map{|i|string[i*size,size]}
end
>> chunk("abcdef",3)
=> ["abc", "def"]
>> chunk("abcde",3)
=> ["abc", "de"]
>> chunk("abc",3)
=> ["abc"]
>> chunk("ab",3)
=> ["ab"]
>> chunk("",3)
=> []
Es posible que desee que el chunk("", n)
devuelva [""]
lugar de []
. Si es así, simplemente agregue esto como la primera línea del método:
return [""] if string.empty?
¿Recomendarías alguna mejor solución?
Editar
Gracias a Jeremy Ruten por esta solución elegante y eficiente:
def chunk(string, size)
string.scan(/.{1,#{size}}/)
end
¿Hay alguna otra restricción que tengas en mente? De lo contrario, estaría tremendamente tentado de hacer algo tan simple como
[0..10].each {
str[(i*w),w]
}
Aquí hay otra manera de hacerlo:
"abcdefghijklmnopqrstuvwxyz".chars.to_a.each_slice(3).to_a.map {|s| s.to_s }
=> ["abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz"]
Creo que esta es la solución más eficiente si sabes que tu cadena es un múltiplo de tamaño de fragmento
def chunk(string, size)
(string.length / size).times.collect { |i| string[i * size, size] }
end
y por partes
def parts(string, count)
size = string.length / count
count.times.collect { |i| string[i * size, size] }
end
Use String#scan
:
>> ''abcdefghijklmnopqrstuvwxyz''.scan(/.{4}/)
=> ["abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx"]
>> ''abcdefghijklmnopqrstuvwxyz''.scan(/.{1,4}/)
=> ["abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx", "yz"]
>> ''abcdefghijklmnopqrstuvwxyz''.scan(/.{1,3}/)
=> ["abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz"]
test.split(/(...)/).reject {|v| v.empty?}
El rechazo es necesario porque de lo contrario incluye el espacio en blanco entre los conjuntos. Mi regex-fu no está a la altura de ver cómo arreglar eso directamente de mi cabeza.