Обрезать строку, если она слишком длинная

У меня есть две строки:

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

пример

  • Тест: я образец фразы, чтобы показать результат этой функции.
  • НЕ: я пример фразы, чтобы показать результат...
  • НО: я образец фразы, чтобы показать результат...

Примечание: я открыт для улучшений, потому что я убежден, что возможно более короткое решение.

Другие вопросы по тегам