Подтвердить что ты не робот

Ruby: подстрока до определенной длины, а также для последнего пробела в подстроке

Я пытаюсь усечь длинную строку текста до определенной длины, но хочу также убедиться, что усеченный результат заканчивается в пробеле. Затем я также добавлю многоточие.

Например:

"This is a very long string that has more characters than I want in it."

становится следующим:

"This is a very long string that..."

Я начинаю с этого, но, очевидно, это не касается проблемы окончания строки в пробеле.

<%= item.description[0..30] %>&hellip;
4b9b3361

Ответ 1

s[0..30].gsub(/\s\w+\s*$/, '...')

Оригинальный ответ не работал в случае, когда 30-символьная подстрока закончилась символом пробела. Это решает это.

>> desc="This is some text it is really long"

>> desc[0..30].gsub(/\s\w+$/,'...')
"This is some text it is really "

>> desc[0..30].gsub(/\s\w+\s*$/,'...')
"This is some text it is..."

Ответ 2

Если вы используете Rails 4, вы должны просто использовать встроенный truncate вспомогательный метод, например:

<%= truncate item.description, :length   => 30, :separator => /\w/,
                               :omission => "&hellip;" %>

Для Rails 3.x параметр :separator должен быть строкой. Предоставление :separator => ' ' должно быть прекрасным в большинстве случаев, но только ловит пробелы, а не другие пробелы. Одним из компромиссов будет использование String#squish, который заменяет все последовательности пробелов одним пространством (а также обрезает начальное и конечное пробелы), например. "foo\n\tbar ".squish дает "foo bar". Это будет выглядеть так:

<%= truncate item.description.squish, :length => 30, :separator => /\w/,
                                      :omission => "&hellip;" %>

Ответ 3

@evfwcqcg ответ очень хорош. Я нашел, что это не сработало, когда

  • Строка содержит другие символы, которые не являются пробелами, а не буквенно-цифровыми.
  • Строка короче искомой длины.

Демонстрация:

>> s = "How about we put some ruby method Class#Method in our string"
=> "How about we put some ruby method Class#Method in our string"
>> s[0..41].gsub(/\s\w+\s*$/, '...')
=> "How about we put some ruby method Class#Me"
>> s[0..999].gsub(/\s\w+\s*$/, '...')
=> "How about we put some ruby method Class#Method in our..."

Это не то, что я ожидал.

Вот что я использую, чтобы исправить это:

def truncate s, length = 30, ellipsis = '...'
  if s.length > length
    s.to_s[0..length].gsub(/[^\w]\w+\s*$/, ellipsis)
  else
    s
  end
end

При выполнении тестов, вот вывод:

>> s = "This is some text it is really long"
=> "This is some text it is really long"
>> truncate s
=> "This is some text it is..."

Все еще ведут себя так, как ожидалось.

>> s = "How about we put some ruby method Class#Method in our string"
=> "How about we put some ruby method Class#Method in our string"
>> truncate s, 41
=> "How about we put some ruby method Class..."
>> truncate s, 999
=> "How about we put some ruby method Class#Method in our string"

Это больше похоже на это.

Ответ 4

desc.gsub(/([\w\s]{30}).+/,'\1...')

Развернув ответ на @evfwcqcg, это чистое регулярное выражение, которое решает проблему конечных пробелов.

irb(main):031:0> desc="This is some text it is really long"
irb(main):033:0> desc.gsub(/([\w\s]{30}).+/,'\1...')
=> "This is some text it is really..."
irb(main):034:0> desc="This is some text it is really"
=> "This is some text it is really"
irb(main):035:0> desc.gsub(/([\w\s]{30}).+/,'\1...')
=> "This is some text it is really"
irb(main):036:0> desc="This is some text it is real"
=> "This is some text it is real"
irb(main):037:0> desc.gsub(/([\w\s]{30}).+/,'\1...')
=> "This is some text it is real"

Ответ 5

class String
  def trunca(length=100, ellipsis='...')
    self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip
  end
end

Пример:

-bash> irb
2.0.0p247 :001 > class String
2.0.0p247 :002?>     def trunca(length=100, ellipsis='...')
2.0.0p247 :003?>         self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip
2.0.0p247 :004?>       end
2.0.0p247 :005?>   end
 => nil 
2.0.0p247 :006 > s = "This is a very long string that has more characters than I want to display."
 => "This is a very long string that has more characters than I want to display." 
2.0.0p247 :007 > s.trunca(20)
 => "This is a very long..." 
2.0.0p247 :008 > s.trunca(31)
 => "This is a very long string that..." 

Ответ 6

Я удивлен, что ни один из ответов не является действительно правильным (или ограничен с помощью помощника rails), хотя это очень старый вопрос, так что вот решение.

Давайте четко сформулируем, какова цель. Мы хотим обрезать строку s до 30 символов и вырезать последнее слово, если оно не может полностью вписаться. Мы также хотим усечь конечные пробелы из результата и добавить многоточие, если текст был сокращен.

Если текст длиннее, чем предел, чем сокращение, так же просто, как

s[0,s.rindex(/\s/,30)].rstrip + '...'

Если бы мы хотели, чтобы весь результат был не более 30 символов, он был таким же простым, как вычитание длины эллипса из 30. Поэтому, поскольку мы используем три точки (а не один трехточечный символ), чем нам нужно

s[0,s.rindex(/\s/,27)].rstrip + '...'

И конечным результатом (с тестом, нужно ли вообще обрезать) является:

if s.length<=30
  s
else
  s[0,s.rindex(/\s/,27)].rstrip + '...'
end

Вот оно.


Примечание. Существуют некоторые тенистые случаи, когда желаемый результат не очевиден. Вот они:

  • Если строка заканчивается большим количеством пробелов (s= "Helo word "), но короче 30. Должны ли сохраняться пробелы? - В настоящее время они есть.
  • То же, что и выше, но пробелы в конце пересекают предел o 30. Как и в (s= "Twentyseven chars long text ") - В настоящее время все пробелы ad end усекаются и добавляется многоточие.