Ruby: substallation sur une certaine longueur et aussi pour durer des espaces dans le sous-chaîne

StackOverflow https://stackoverflow.com/questions/9503554

  •  14-11-2019
  •  | 
  •  

Question

J'essaie de tronquer une longue chaîne de texte sur une certaine longueur, mais je veux également m'assurer que le résultat tronqué se termine à un espace blanc. Je vais également ajouter une ellipse par la suite.

Par exemple ceci:

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

devient ceci:

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

Je commence par cela, mais évidemment cela ne traite pas du problème de la fin de la chaîne sur l'espace.

<%= item.description[0..30] %>&hellip;
Était-ce utile?

La solution

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

La réponse originale n'a pas fonctionné dans le cas où la sous-chaîne de 30 caractères s'est terminée sur un caractère blanc. Cela résout cela.

>> 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..."

Autres conseils

Si vous utilisez Rails 4+, vous devez simplement utiliser le truncate Méthode d'aide, par exemple:

<%= truncate item.description, length: 30, separator: /\w+/ %>

La chaîne "…" sera annexée au texte tronqué; Pour spécifier une chaîne différente, utilisez le :omission option, par exemple omission: "xxx".

Pour rails 3.x le :separator L'option doit être une chaîne. Donnant :separator => " " Sera bien dans de nombreux cas, mais n'attrape que les espaces et non d'autres espaces. Un compromis serait à utiliser String#squish, qui remplace toutes les séquences de Whitespace par un seul espace (et aussi une coupe en tête et un espace blanc), par exemple "foo\n\tbar ".squish rendements "foo bar". Cela ressemblerait à ceci:

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

La réponse de @ EVFWCQCG est très bonne. J'ai trouvé que cela ne fonctionnait pas bien quand

  1. La chaîne contenait d'autres caractères non espaces et non alphanumériques.
  2. La chaîne est plus courte que la longueur souhaitée.

Manifestation:

>> 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..."

Ce n'est pas ce à quoi je m'attendais.

Voici ce que j'utilise pour résoudre ce problème:

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

Lorsque vous effectuez des tests, voici la sortie:

>> 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..."

Se comporte toujours comme prévu.

>> 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"

C'est plus comme ça.

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

En étendant la réponse de @EVFWCQCG, c'est un pur regex qui résout le problème de la traîne Whitespace.

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"

Je suis surpris qu'aucune des réponses ne soit vraiment correcte (ou limitée en utilisant Rails Helper) bien que ce soit une très vieille question, alors voici la solution.

Permet de formuler clairement ce que le but est d'abord. Nous voulons tronquer la chaîne s à 30 caractères et découper également le dernier mot s'il ne peut pas s'adapter entièrement. Nous voulons également tronquer des espaces de fuite du résultat et ajouter des ellipses, si le texte a été raccourci.

Si le texte est plus long, alors le raccourcissement est aussi simple que

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

Si nous voulions que le résultat entier soit max 30 caractères, il est aussi simple que de soustraire la longueur de l'ellipse de 30. Donc, parce que nous utilisons trois points (et pas un caractère à trois points), nous avons besoin

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

Et le résultat final (avec le test si nous devons tronquer du tout) est:

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

C'est ça.


Remarque: il y a des cas ombragés, lorsque le résultat souhaité n'est pas évident. Les voici:

  • Si la chaîne se termine avec beaucoup d'espaces (s= "Helo word ") Mais est plus court que 30. Les espaces devraient-ils être préservés? - Actuellement, ils le sont.
  • Comme ci-dessus, mais les espaces à l'extrémité traversent la limite o 30. comme dans (s= "Twentyseven chars long text ") - Actuellement, tous les espaces AD l'extrémité sont tronqués et l'ellipsie ajoutée.
class String
  def trunca(length=100, ellipsis='...')
    self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip
  end
end

Exemple:

-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..." 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top