2013-09-27 9 views
5

Mam dwa ciągi:Obetnij ciąg, gdy jest zbyt długo

short_string = "hello world" 
long_string = "this is a very long long long .... string" # suppose more than 10000 chars 

Chcę zmienić domyślne zachowanie print do:

puts short_string 
# => "hello world" 
puts long_string 
# => "this is a very long long....." 

The long_string jest tylko częściowo drukowane. Próbowałem zmienić String#to_s, ale to nie zadziałało. Czy ktoś wie, jak to zrobić w ten sposób?

aktualizowane

Właściwie chcę to działa płynnie, co oznacza następujące przypadki również działa dobrze:

> puts very_long_str 
> puts [very_long_str] 
> puts {:a => very_long_str} 

więc myślę, że zachowanie należy do String.

Dzięki wszystko.

Odpowiedz

9

Tak to robi Ruby on Rails w swojej metodzie String#truncate.

def truncate(truncate_at, options = {}) 
    return dup unless length > truncate_at 

    options[:omission] ||= '...' 
    length_with_room_for_omission = truncate_at - options[:omission].length 
    stop =  if options[:separator] 
     rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission 
    else 
     length_with_room_for_omission 
    end 

    "#{self[0...stop]}#{options[:omission]}" 
end 

Wtedy można go używać jak to

'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)') 
# => "And they f... (continued)" 

i Tak. Został dodany do Rails jako monkey-patch. Więc jego realizowane tak:

class String 
    def truncate.. 
    end 
end 
3

Możesz napisać otoki wokół puts który obsługuje obcinanie dla Ciebie:

def pleasant(string, length = 32) 
    raise 'Pleasant: Length should be greater than 3' unless length > 3 

    truncated_string = string.to_s 
    if truncated_string.length > length 
    truncated_string = truncated_string[0...(length - 3)] 
    truncated_string += '...' 
    end 

    puts truncated_string 
    truncated string 
end 
+0

Naprawiono kilka problemów z kodem. – kristinalim

+1

Zwraca 'nil', co sprawia, że ​​testowanie jest trudniejsze. Prawdopodobnie powinien po prostu zwrócić ścięty ciąg znaków. – vgoff

+0

Zaktualizowana odpowiedź, aby zwrócić skrócone ciągi, jak zasugerował @vgoff. – kristinalim

11

Przede wszystkim, trzeba metodę truncate ciąg, albo coś takiego:

def truncate(string, max) 
    string.length > max ? "#{string[0...max]}..." : string 
end 

Albo poprzez rozszerzenie String:

class String 
    def truncate(max) 
    length > max ? "#{self[0...max]}..." : self 
    end 
end 

Teraz można zadzwonić truncate podczas drukowania ciąg:

puts "short string".truncate 
#=> short string 

puts "a very, very, very, very long string".truncate 
#=> a very, very, very, ... 

Albo można po prostu zdefiniować własne puts:

def puts(string) 
    super(string.truncate(20)) 
end 

puts "short string" 
#=> short string 

puts "a very, very, very, very long string" 
#=> a very, very, very, ... 

Zauważ, że Kernel#puts trwa zmienną liczbę argumentów, to może chcieć aby zmienić odpowiednio metodę puts.

0

Obetnij naturalnie

Chcę zaproponować rozwiązanie, które obcina naturalnie. Zakochałem się w String#truncate method oferowanej przez Ruby on Rails. Było to już wspomniane przez @Oto Brglez powyżej. Niestety nie mogłem przepisać go dla czystego rubinu. Więc napisałem tę funkcję.

def truncate(content, max)  
    if content.length > max 
     truncated = "" 
     collector = "" 
     content = content.split(" ") 
     content.each do |word| 
      word = word + " " 
      collector << word 
      truncated << word if collector.length < max 
     end 
     truncated = truncated.strip.chomp(",").concat("...") 
    else 
     truncated = content 
    end 
    return truncated 
end 

Przykład

  • testu: Ja wyrażenie próbka przedstawiają wynik tej funkcji.
  • NIE: Jestem fraza próbkę aby pokazać wynik th ...
  • ALE: Jestem fraza próbkę aby pokazać wynik ...

Uwaga: jestem otwarty na ulepszenia, ponieważ jestem przekonany, że możliwe jest krótsze rozwiązanie.

Powiązane problemy