Обрезать строку, если она слишком длинная
У меня есть две строки:
short_string = "hello world"
long_string = "this is a very long long long .... string" # suppose more than 10000 chars
Я хочу изменить поведение по умолчанию print
чтобы:
puts short_string
# => "hello world"
puts long_string
# => "this is a very long long....."
long_string
только частично напечатан. Я пытался изменить String#to_s
, но это не сработало. Кто-нибудь знает, как это сделать?
обновленный
На самом деле я хочу, чтобы это работало гладко, это означает, что следующие случаи также работают нормально:
> puts very_long_str
> puts [very_long_str]
> puts {:a => very_long_str}
Так что я думаю, что поведение принадлежит String.
В любом случае, спасибо.
5 ответов
Прежде всего, вам нужен метод truncate
строка, либо что-то вроде:
def truncate(string, max)
string.length > max ? "#{string[0...max]}..." : string
end
Или путем расширения String
: (однако не рекомендуется менять основные классы)
class String
def truncate(max)
length > max ? "#{self[0...max]}..." : self
end
end
Теперь вы можете позвонить truncate
при печати строки:
puts "short string".truncate
#=> short string
puts "a very, very, very, very long string".truncate
#=> a very, very, very, ...
Или вы можете просто определить свой собственный 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, ...
Обратите внимание, что Kernel#puts
принимает переменное количество аргументов, вы можете изменить puts
метод соответственно.
Вот как это делает Ruby on Rails в своем методе 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
Тогда вы можете использовать это так
'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
# => "And they f... (continued)"
И да. Его добавили в Rails как monkey-patch. Так что это реализовано так:
class String
def truncate..
end
end
Вы можете просто использовать этот синтаксис:
"mystring"[0..MAX_LENGTH]
[5] pry(main)> "hello world"[0..10]
=> "hello world"
[6] pry(main)> "hello world why"[0..10]
=> "hello world"
[7] pry(main)> "hello"[0..10]
=> "hello"
Нет необходимости проверять, действительно ли она превышает максимальную длину.
Вы можете написать обертку вокруг puts
который обрабатывает усечение для вас:
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
Усекать естественно
Я хочу предложить решение, которое усекается естественным образом. Я влюбился в метод String#truncate, предложенный Ruby on Rails. Это уже упоминалось @Oto Brglez выше. К сожалению, я не смог переписать его на чистый рубин. Вот я и написал эту функцию.
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
пример
- Тест: я образец фразы, чтобы показать результат этой функции.
- НЕ: я пример фразы, чтобы показать результат...
- НО: я образец фразы, чтобы показать результат...
Примечание: я открыт для улучшений, потому что я убежден, что возможно более короткое решение.