Les chaînes et les symboles
Ce guide approfondit les String et les Symbol introduits au chapitre 1. On découvre les outils que Ruby offre pour transformer, formater et comparer du texte.
Principe
On a vu qu'une String est du texte et qu'un Symbol est un identifiant. Dans ce chapitre, on va apprendre à manipuler les String : les modifier, les découper, les aligner. On verra aussi pourquoi les Symbol sont si importants et comment passer de l'un à l'autre.
Rappel : guillemets simples et doubles
Les guillemets simples créent un texte brut. Les guillemets doubles permettent l'interpolation (#{}) et les séquences d'échappement :
\ncrée un retour à la ligne.\tcrée une tabulation. Ces séquences ne fonctionnent qu'avec les guillemets doubles.- Règle simple : guillemets simples par défaut, guillemets doubles si on a besoin d'interpolation ou de
\n.
Les textes multi-lignes (heredoc)
Pour écrire un texte sur plusieurs lignes sans enchaîner les \n, Ruby propose les heredoc :
description = <<~TEXT
Pikachu est un Pokémon de type Électrik.
Il évolue depuis Pichu par bonheur.
TEXT
puts description
<<~TEXTouvre le heredoc. Le texte se termine quand Ruby rencontreTEXTseul sur une ligne.- Le
~supprime l'indentation commune, ce qui permet d'indenter le texte dans le code sans que les espaces apparaissent à l'affichage. - Le mot
TEXTest un choix arbitraire. On pourrait écrire<<~DESCRIPTIONou n'importe quel autre mot.
Interpolation vs concaténation
Il y a deux façons de combiner du texte et des variables. La première, l'interpolation, on la connaît déjà :
name = 'Dracaufeu'
level = 36
# Interpolation (à privilégier)
puts "#{name} est niveau #{level}"
# Concaténation (à éviter)
puts name + ' est niveau ' + level.to_s
- L'interpolation convertit automatiquement les valeurs en texte. La concaténation exige un appel à
.to_ssinon Ruby lève une erreur. - L'interpolation est plus lisible, plus courte, et plus performante. C'est toujours le bon choix.
Connaître la taille d'une String
puts 'Pikachu'.length # => 7
puts 'Pikachu'.size # => 7
puts ''.length # => 0
.lengthet.sizefont exactement la même chose. Utiliser l'un ou l'autre, c'est une question de préférence.
Changer la casse
Ruby offre plusieurs méthodes pour changer les majuscules et minuscules :
.upcasemet tout en majuscules..downcasemet tout en minuscules..capitalizemet la première lettre en majuscule et le reste en minuscules..swapcaseinverse chaque lettre (majuscule devient minuscule et vice versa). C'est rarement utile, mais bon à connaître.
Supprimer les espaces
name = ' Pikachu '
puts name.strip # => "Pikachu" (supprime les espaces des deux côtés)
puts name.lstrip # => "Pikachu " (supprime à gauche seulement)
puts name.rstrip # => " Pikachu" (supprime à droite seulement)
.stripest très utile quand on récupère du texte saisi par un utilisateur, qui contient souvent des espaces en trop.
Chercher dans une String
puts 'Bulbizarre'.include?('zarre') # => true
puts 'Bulbizarre'.include?('Feu') # => false
puts 'Bulbizarre'.start_with?('Bulb') # => true
puts 'Bulbizarre'.end_with?('zarre') # => true
- Ces méthodes retournent
trueoufalse. Le?à la fin est la convention Ruby pour les méthodes qui posent une question. - La recherche est sensible à la casse :
'Pikachu'.include?('pika')retournefalse.
Remplacer du texte
phrase = 'Pikachu utilise Tonnerre. Pikachu gagne !'
# Remplacer la première occurrence
puts phrase.sub('Pikachu', 'Raichu')
# => Raichu utilise Tonnerre. Pikachu gagne !
# Remplacer toutes les occurrences
puts phrase.gsub('Pikachu', 'Raichu')
# => Raichu utilise Tonnerre. Raichu gagne !
.subremplace uniquement la première occurrence..gsubremplace toutes les occurrences (legsignifie "global").- Ces méthodes retournent une nouvelle String. L'originale n'est pas modifiée.
Répéter une String
L'opérateur * permet de répéter une String :
puts '=' * 30 # => ==============================
puts 'Pika' * 3 # => PikaPikaPika
- C'est très pratique pour créer des lignes de séparation ou des barres visuelles.
Aligner du texte
Ruby permet d'aligner du texte dans un espace de largeur fixe :
puts 'Pikachu'.ljust(15) # => "Pikachu "
puts 'Pikachu'.rjust(15) # => " Pikachu"
puts 'Pikachu'.center(15) # => " Pikachu "
puts 'Pikachu'.center(15, '-') # => "----Pikachu----"
.ljust(n)aligne à gauche surncaractères en remplissant avec des espaces à droite..rjust(n)aligne à droite..center(n)centre le texte.- On peut remplacer l'espace par un autre caractère en le passant en second argument.
Formater des nombres dans du texte
Pour afficher un nombre avec un format précis (zéros en tête, décimales fixes), Ruby offre la méthode format :
pokedex_number = 6
health = 88.5
puts format('No.%03d', pokedex_number) # => No.006
puts format('PV: %.1f%%', health) # => PV: 88.5%
%03dsignifie : un entier (d) sur au moins 3 caractères (3), complété par des zéros (0).%.1fsignifie : un nombre décimal (f) avec 1 chiffre après la virgule.%%affiche un vrai%(sinon Ruby pense que c'est un format).
Les Symbol en profondeur
On a vu au chapitre 1 que les Symbol sont des identifiants. Voyons pourquoi ils sont différents des String :
# Deux Symbol identiques sont le même objet en mémoire
puts :fire.object_id # => toujours le même nombre
puts :fire.object_id # => exactement le même nombre
# Deux String identiques sont des objets différents
puts 'fire'.object_id # => un nombre
puts 'fire'.object_id # => un nombre différent !
- Chaque fois qu'on écrit
'fire', Ruby crée un nouvel objet en mémoire. Chaque fois qu'on écrit:fire, Ruby réutilise le même objet. - C'est pour cela que la comparaison entre Symbol est instantanée : Ruby compare juste un numéro, pas chaque caractère un par un.
Convertir entre String et Symbol
type_symbol = :fire
type_string = type_symbol.to_s # => "fire"
type_string = 'water'
type_symbol = type_string.to_sym # => :water
.to_sconvertit un Symbol en String..to_symconvertit une String en Symbol.- On a parfois besoin de ces conversions pour afficher un Symbol (qui ne peut pas être interpolé tel quel sans
.to_s, mais l'interpolation appelle.to_sautomatiquement).
Quand utiliser String vs Symbol
- Symbol : pour tout ce qui est un identifiant interne. Un type de Pokémon (
:fire), un statut (:poisoned), une clé dans une structure de données. - String : pour tout ce qui est du texte affiché ou manipulé. Un nom de Pokémon (
'Pikachu'), une description, un message.
En cas de doute : est-ce qu'on va afficher cette valeur à l'utilisateur ? Si oui, c'est une String. Est-ce qu'on va l'utiliser comme étiquette pour identifier quelque chose ? Si oui, c'est un Symbol.
Conclusion
- Les guillemets simples créent un texte brut. Les guillemets doubles permettent l'interpolation et les séquences d'échappement (
\n,\t). - Toujours préférer l'interpolation à la concaténation.
.upcase,.downcase,.capitalizechangent la casse..stripsupprime les espaces..include?,.start_with?,.end_with?cherchent dans une String..subremplace la première occurrence,.gsubtoutes les occurrences.*répète une String..ljust,.rjust,.centeralignent du texte.formatpermet de formater des nombres avec des zéros en tête ou des décimales fixes.- Les Symbol sont immuables et uniques en mémoire. Utiliser
.to_set.to_sympour convertir.