Как я могу центрировать усеченную строку? - PullRequest
14 голосов
/ 20 сентября 2009

У кого-нибудь есть какой-нибудь удобный код, который по центру усекает строку в Ruby on Rails?

Примерно так: Пример: "Привет, мир, как дела?" => "Хел ... ты?"

Ответы [ 11 ]

29 голосов
/ 13 октября 2013

Если вам нужна определенная фиксированная длина независимо от длины строки, вы можете использовать Rails #truncate:

s.truncate(100, omission: "...#{s.last(50)}")
13 голосов
/ 20 сентября 2009

Как насчет версии Regex:

class String
  def ellipsisize
    gsub(/(...).{4,}(...)/, '\1...\2')
  end
end

"abc".ellipsisize #=> "abc"
"abcdefghi".ellipsisize #=> "abcdefghi"
"abcdefghij".ellipsisize #=> "abc...hij"

РЕДАКТИРОВАТЬ: как предложено в комментариях, параметризованная длина (и с использованием другой нотации Regex, просто для чертовски)

class String
  def ellipsisize(len = 9)
    len = 9 unless len > 9 # assumes minimum chars at each end = 3
    gsub(%r{(...).{#{len-5},}(...)}, '\1...\2')
  end
end

так ...

"abcdefghij".ellipsisize #=> "abc...hij"

но мы также можем:

"abcdefghij".ellipsisize(10) #=> "abcdefghij"
10 голосов
/ 21 сентября 2009

Вот модифицированная версия ответа Майка Вудхауса. Требуется 2 необязательных параметра: минимальная длина для строки, подлежащей эллипсизму, и длина края.

class String
  def ellipsisize(minimum_length=4,edge_length=3)
    return self if self.length < minimum_length or self.length <= edge_length*2 
    edge = '.'*edge_length    
    mid_length = self.length - edge_length*2
    gsub(/(#{edge}).{#{mid_length},}(#{edge})/, '\1...\2')
  end
end


"abc".ellipsisize #=> "abc"
"abcdefghi".ellipsisize #=> "abcdefghi"
"abcdefghij".ellipsisize #=> "abc...hij"
"abcdefghij".ellipsisize(4,4) #=> "abcd...ghij"
"Testing all paramas and checking them!".ellipsisize(6,5) #=> "Testi...them!"
5 голосов
/ 20 сентября 2009

Вот мое предложение:

s[3...-4] = "..." if s.length > 9
5 голосов
/ 20 сентября 2009

Поскольку вы не указали, сколько символов вы хотите обрезать, я предполагаю (из вашего примера), что вы хотите обрезать строки, длина которых превышает шесть. Затем вы можете использовать что-то вроде этого:

s = "Hello World, how are you?"
s = s[0, 3] + "..." + s[-3, 3] if s.length > 9
=> "Hel...ou?"

Просто измените диапазоны, если вам нужно усечь больше символов.

3 голосов
/ 24 августа 2011
class String
  # https://gist.github.com/1168961
  # remove middle from strings exceeding max length.
  def ellipsize(options={})
    max = options[:max] || 40
    delimiter = options[:delimiter] || "..."
    return self if self.size <= max
    remainder = max - delimiter.size
    offset = remainder / 2
    (self[0,offset + (remainder.odd? ? 1 : 0)].to_s + delimiter + self[-offset,offset].to_s)[0,max].to_s
  end unless defined? ellipsize
end
1 голос
/ 19 декабря 2014

Другой способ:

class String
  def middle_truncate(len)
    return self if len >= size
    return self[0...len] unless len > 4
    half = len / 2.0
    (result = dup)[(half - 1.5).floor...(1.5 - half).floor] = '...'
    result
  end
end

Это дает дополнительное преимущество - просто усечение, если размер строки <5. </p>

например. для струны четного размера:

2.1.1 :001 > s = "12345678901234567890"
 => "12345678901234567890" 
2.1.1 :002 > s.middle_truncate 21
 => "12345678901234567890" 
2.1.1 :003 > s.middle_truncate 20
 => "12345678901234567890" 
2.1.1 :004 > s.middle_truncate 19
 => "12345678...34567890" 
2.1.1 :005 > s.middle_truncate 18
 => "1234567...34567890" 
2.1.1 :006 > s.middle_truncate 5
 => "1...0" 
2.1.1 :007 > s.middle_truncate 4
 => "1234" 

и для строки нечетного размера:

2.1.1 :012 > s = "123456789012345678901"
 => "123456789012345678901" 
2.1.1 :013 > s.middle_truncate 22
 => "123456789012345678901" 
2.1.1 :014 > s.middle_truncate 21
 => "123456789012345678901" 
2.1.1 :015 > s.middle_truncate 20
 => "12345678...345678901" 
2.1.1 :016 > s.middle_truncate 19
 => "12345678...45678901" 
2.1.1 :017 > s.middle_truncate 5
 => "1...1" 
2.1.1 :018 > s.middle_truncate 4
 => "1234" 
0 голосов
/ 18 июня 2019

Модифицированная версия рельсов, которая усекается только с середины

def middle_truncate(str, total: 30, lead: 15, trail: 15)
  str.truncate(total, omission: "#{str.first(lead)}...#{str.last(trail)}")
end
0 голосов
/ 14 августа 2017

Это самый простой способ для меня:

def ellipsisize(text, minimum_length=12,edge_length=4)
  leftover = text.length - minimum_length
  edge_length = leftover if (edge_length > leftover && leftover >= 0)
  edge_length = 0 if leftover < 0

  return text.truncate(minimum_length) << text.last(edge_length)
end

С уважением, ребята!

0 голосов
/ 31 января 2014

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

Вот решение, которое использует размер в байтах и ​​сохраняет Unicode текстовые элементы без изменений (которые не всегда совпадают с Unicode символами ). Протестировано в Ruby 1.8 / 1.9 / 2.0.

Это может быть улучшено, чтобы быть более эффективным для очень длинных строк, которые должны быть обрезаны до гораздо меньшей длины.

Вы должны установить гем Юникода.

require 'unicode'

# truncates a unicode string like:
#   >> truncate_string_middle('12345678', 5)
#   => "1...8"
def truncate_string_middle(str, limit, ellipsis='...')
  raise "limit (#{limit}) must not be less than the ellipsis size (#{ellipsis.bytesize})" if limit < ellipsis.bytesize

  return str if str.bytesize <= limit

  chars = Unicode.text_elements(str)
  split_point = (chars.size/2.0).ceil
  front, back = chars[0...split_point], chars[split_point..-1]

  pop_front = chars.size.odd?
  # alternate between popping from the front and shifting from the back until it's small enough
  while (front.join + ellipsis + back.join).bytesize > limit
    if pop_front
      front.pop
    else
      back.shift
    end
    pop_front = !pop_front
  end

  front.join + ellipsis + back.join
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...