2011-01-11 10 views
26

Nie jestem pewien, jak to zrobić, ponieważ jestem całkiem nowy w wyrażeniach regularnych i nie mogę znaleźć odpowiedniej metody, aby to osiągnąć, ale mówię, że mam następujące jako smyczkowe (wszystkie zakładki oraz nowe linie włączone)Ruby zmniejszyć wszystkie odstępy do pojedynczych spacji

1/2 cup 




      onion   
      (chopped) 

Jak mogę usunąć wszystkie spacje i zastąpić każde wystąpienie z tylko jednego miejsca?

Odpowiedz

53

Jest to przypadek, w którym wyrażenia regularne działa dobrze, ponieważ chcemy, aby traktować całą klasę białych znaków tak samo i zastąpić serie dowolnej kombinacji białych znaków z pojedynczy znak spacji. Więc jeśli ciąg jest przechowywany w s, wtedy można zrobić:

fixed_string = s.gsub(/\s+/, ' ') 
+1

To jest poprawna odpowiedź. I ładne imię, mogę dodać . :) –

8

Chcesz sposób przymusowy:

str.squeeze([other_str]*) → new_str 
Builds a set of characters from the other_str parameter(s) using the procedure described for String#count. Returns a new string where runs of the same character that occur in this set are replaced by a single character. If no arguments are given, all runs of identical characters are replaced by a single character. 

    "yellow moon".squeeze     #=> "yelow mon" 
    " now is the".squeeze(" ")   #=> " now is the" 
    "putters shoot balls".squeeze("m-z") #=> "puters shot balls" 
+1

To nie do końca prawda, jak sądzę. Spowoduje to tylko kompresję przebiegów kart w jednej zakładce i uruchamianie linii nowego wiersza w pojedynczy znak nowej linii. Kiedy go czytam, pojawia się pytanie, w jaki sposób zastąpić ciągi dowolnych kombinacji białych znaków z pojedynczym znakiem spacji. – Chuck

+0

Szkoda, że ​​'String.squeeze' nie przyjmuje wyrażenia regularnego jako argumentu. Awansuj, jeśli uważasz, że byłby to dobry pomysł; Mógłbym złożyć PR. – the911s

+2

również to usuwa duplikaty, np. "class" staje się "clas", co może być złamaniem umowy, jeśli uruchomisz to na html, tym bardziej właściwą metodą (jeśli w szynach) będzie String # squish – engineerDave

3

Wybrana odpowiedź nie usunie non-breaking space znaków.

To powinno działać w 1,9:

fixed_string = s.gsub(/(\s|\u00A0)+/, ' ')

+0

Zakładam, że OP chciał usunąć pozbawione znaczenia białe spacje (tj. Przebiegi z więcej niż jednej spacji), aby uporządkować i zmniejszyć rozmiar ciągów przeznaczonych do HTML, ponieważ wiele kolejnych znaków odstępu zostanie zwiniętych w jedną przestrzeń przez przeglądarki internetowe w każdym razie ... Warto zauważyć, że nie łamiące się spacje nie mają znaczenia w HTML, nie są zwinięte, tzn. prawdopodobnie nie chcą ich usuwać – callum

4

Problem z najprostszego rozwiązania gsub(/\s+/, ' ') jest to, że jest bardzo powolny, gdyż zastępuje każdą przestrzeń, nawet jeśli jest to pojedynczy. Ale zwykle jest 1 spacja między słowami i powinniśmy ją naprawić tylko wtedy, gdy są 2 lub więcej białych znaków w sekwencji.

lepszym rozwiązaniem jest gsub(/[\r\n\t]/, ' ').gsub(/ {2,}/, ' ') - najpierw pozbyć specjalnych whitespaces a następnie wycisnąć przestrzeni normalnych

def method1(s) s.gsub!(/\s+/, ' '); s end 
def method2(s) s.gsub!(/[\r\n\t]/, ' '); s.gsub!(/ {2,}/, ' '); s end 

Benchmark.bm do |x| 
    n = 100_000 
    x.report('method1') { n.times { method1("Lorem ipsum\n\n dolor \t\t\tsit amet, consectetur\n \n\t\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") } } 
    x.report('method2') { n.times { method2("Lorem ipsum\n\n dolor \t\t\tsit amet, consectetur\n \n\t\n adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") } } 
end;1 

#  user  system  total  real 
# method1 4.090000 0.010000 4.100000 ( 4.124844) 
# method2 1.590000 0.010000 1.600000 ( 1.611443) 
11

ciągu Rails można użyć String#squish, który jest active_support rozszerzenia.

require 'active_support' 

s = <<-EOS 
1/2 cup 

      onion 
EOS 

s.squish 
# => 1/2 cup onion 
Powiązane problemy