it-swarm.com.de

Was ist der beste Weg, um eine Zeichenfolge in Ruby in Stücke einer bestimmten Länge zu schneiden?

Ich habe nach einer eleganten und effizienten Methode gesucht, eine Zeichenkette in Teilzeichenfolgen einer bestimmten Länge in Ruby zu unterteilen.

Das Beste, was ich bisher finden konnte, ist folgendes:

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)
=> []

Möglicherweise möchten Sie, dass chunk("", n)[""] anstelle von [] zurückgegeben wird. Wenn ja, fügen Sie dies einfach als erste Zeile der Methode hinzu:

return [""] if string.empty?

Würden Sie eine bessere Lösung empfehlen?

Bearbeiten

Danke an Jeremy Ruten für diese elegante und effiziente Lösung:

def chunk(string, size)
    string.scan(/.{1,#{size}}/)
end
81
MiniQuark

Verwenden Sie 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"]
146
Jeremy Ruten

Hier ist eine andere Möglichkeit, dies zu tun:

"abcdefghijklmnopqrstuvwxyz".chars.to_a.each_slice(3).to_a.map {|s| s.to_s }

=> ["abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz"]

17
Jason

Ich denke, dies ist die effizienteste Lösung, wenn Sie wissen, dass Ihre Zeichenfolge ein Vielfaches der Chunk-Größe ist

def chunk(string, size)
    (string.length / size).times.collect { |i| string[i * size, size] }
end

und für Teile

def parts(string, count)
    size = string.length / count
    count.times.collect { |i| string[i * size, size] }
end
5
davispuh

Hier ist eine andere Lösung für den etwas anderen Fall, wenn große Strings verarbeitet werden, und es ist nicht erforderlich, alle Blöcke gleichzeitig zu speichern. Auf diese Weise werden einzelne Blöcke gleichzeitig gespeichert und sind wesentlich schneller als das Schneiden von Strings:

io = StringIO.new(string)
until io.eof?
  chunk = io.read(chunk_size)
  do_something(chunk)
end
1
prcu
test.split(/(...)/).reject {|v| v.empty?}

Die Zurückweisung ist notwendig, da ansonsten der Leerraum zwischen Sätzen enthalten ist. Mein Regex-Fu ist nicht ganz darauf aus, wie ich das direkt aus meinem Kopf heraus reparieren kann.

1
Chuck

Eine bessere Lösung, bei der der letzte Teil der Zeichenfolge berücksichtigt wird, der möglicherweise kleiner als die Blockgröße ist:

def chunk(inStr, sz)  
  return [inStr] if inStr.length < sz  
  m = inStr.length % sz                  # this is the last part of the string
  partial = (inStr.length / sz).times.collect { |i| inStr[i * sz, sz] }
  partial << inStr[-m..-1] if m          # add the last part 
end
0
kirkytullins

Gibt es noch andere Einschränkungen, die Sie berücksichtigen? Sonst wäre ich furchtbar versucht, so etwas Einfaches zu tun

[0..10].each {
   str[(i*w),w]
}
0
Charlie Martin