Comment utiliser les méthodes de tableaux en Ruby

introduction

Arrays vous permet de représenter des listes de données dans vos programmes. Une fois que vous avez des données dans un tableau, vous pouvez le trier, supprimer les doublons, inverser son ordre, extraire des sections du tableau ou rechercher dans des tableaux des données spécifiques. Vous pouvez également convertir un tableau en tring, transformer un tableau de données en un autre et le remonter. un tableau en une seule valeur.

Dans ce didacticiel, vous explorerez certaines des méthodes les plus pratiques fournies par Ruby pour travailler avec des données stockées dans des tableaux.

Au cours de ce didacticiel, certaines méthodes se terminant par un point d’exclamation (+! +) Seront visibles. Ces méthodes ont souvent des effets secondaires, tels que la modification de la valeur d’origine ou la génération d’exceptions. De nombreuses méthodes que vous utiliserez dans ce tutoriel ont une méthode associée avec ce suffixe.

Vous rencontrerez également des méthodes qui se terminent par un point d’interrogation (+? +). Ces méthodes renvoient une valeur booléenne.

Ce sont une convention de nommage utilisée dans Ruby. Ce n’est pas quelque chose qui est imposé au niveau du programme; c’est juste un autre moyen d’identifier ce que vous pouvez attendre de la méthode.

Commençons notre exploration des méthodes de tableau en examinant plusieurs façons d’accéder aux éléments.

Accéder aux éléments

Si vous avez déjà suivi le tutoriel How To Work avec des tableaux en Ruby, vous savez que vous pouvez y accéder. un élément individuel utilisant son index, qui est basé sur zéro, comme ceci:

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks[0]    # "Tiger"
sharks[1]    # "Great White"
sharks[-1]   # "Angel"

Vous pouvez également vous rappeler que vous pouvez utiliser les méthodes + first + et + last + pour récupérer le premier et le dernier élément d’un tableau:

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.first   # "Tiger"
sharks.last    # "Angel"

Enfin, lorsque vous accédez à un élément qui n’existe pas, vous obtenez «+ nil ». Mais si vous préférez obtenir une erreur, utilisez la méthode ` fetch +`:

sharks.fetch(42)
OutputIndexError: index 42 outside of array bounds: -4...4

Si vous préférez spécifier votre propre valeur par défaut au lieu de générer une erreur, vous pouvez également le faire:

sharks.fetch(42, "Nope")     # "Nope"

Voyons maintenant comment obtenir plusieurs éléments d’un tableau.

Récupération de plusieurs éléments

Il peut arriver que vous souhaitiez extraire un sous-ensemble de valeurs de votre tableau au lieu d’un seul élément.

Si vous spécifiez un index de départ, suivi du nombre d’éléments souhaité, vous obtiendrez un nouveau tableau contenant ces valeurs. Par exemple, vous pouvez récupérer les deux entrées du milieu dans le tableau + sharks + comme ceci:

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks[1,2]   # ["Great White", "Hammerhead"]

Nous commençons à l’indice + 1 +, qui est " Great White ", et nous spécifions que nous voulons des éléments + 2 +, nous obtenons donc un nouveau tableau contenant " Great White " et ` + "Tête de marteau" + `.

Vous pouvez utiliser la méthode + slice + pour faire la même chose:

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.slice(1,2)   # ["Great White", "Hammerhead"]

La méthode + slice + renvoie également un nouveau tableau, laissant le tableau d’origine inchangé. Toutefois, si vous utilisez la méthode + slice! +, Le tableau d’origine sera également modifié.

La méthode + take + vous permet de récupérer le nombre spécifié d’entrées depuis le début d’un tableau:

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.take(2)  # ["Tiger", "Great White"]

Parfois, vous souhaitez extraire une valeur aléatoire d’un tableau au lieu d’une valeur spécifique. Voyons comment.

Obtenir une entrée aléatoire d’un tableau

Vous travaillez peut-être sur un jeu de hasard ou vous écrivez peut-être un programme qui désigne le gagnant du concours. Ce genre de choses nécessite une sorte de valeur aléatoire. Une solution courante consiste à placer les choix possibles dans un tableau et à sélectionner un index aléatoire.

Pour obtenir un élément aléatoire d’un tableau, vous pouvez générer un index aléatoire entre + 0 + et le dernier index du tableau et l’utiliser comme index pour récupérer la valeur, mais il existe un moyen plus simple: le + + échantillon + méthode récupère une entrée aléatoire dans un tableau.

Utilisons-le pour récupérer une réponse aléatoire parmi une série de réponses, créant ainsi une version primitive d’un jeu Magic 8-Ball:

8ball.rb

answers = ["Yes", "No", "Maybe", "Ask again later"]
print answers.sample
OutputMaybe

La méthode + sample + accepte également un argument qui renvoie un tableau d’entrées aléatoires. Si vous avez besoin de plusieurs entrées aléatoires, indiquez simplement le nombre que vous souhaitez:

random_sharks.rb

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sample = sharks.sample(2)
print sample
Output["Whale", "Great White"]

Voyons maintenant comment trouver des éléments spécifiques dans un tableau.

Recherche et filtrage d’éléments

Lorsque vous recherchez des éléments spécifiques dans un tableau, vous effectuez une itération sur ses éléments jusqu’à ce que vous trouviez ce que vous recherchez. Cependant, les tableaux Ruby fournissent plusieurs méthodes spécialement conçues pour simplifier le processus de recherche dans les tableaux.

Si vous voulez juste voir si un élément existe, vous pouvez utiliser la méthode + include? +, Qui renvoie + true + si la donnée spécifiée est un élément du tableau:

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sharks.include? "Tiger"      # true

["a", "b", "c"].include? 2   # false

Cependant, + include? + Nécessite une correspondance exacte, vous ne pouvez donc pas rechercher un mot partiel.

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sharks.include? "Tiger"      # true
sharks.include? "tiger"      # false
sharks.include? "ti"         # false

La méthode + find + localise et retourne le premier élément du tableau qui correspond à une condition que vous spécifiez.

Par exemple, pour identifier la première entrée du tableau + sharks + contenant la lettre + a +, vous pouvez utiliser la méthode + each + pour comparer chaque entrée et arrêter l’itération lorsque vous trouvez la première, comme ceci:

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = nil
sharks.each do |shark|
 if sharks.include? "a"
   result = shark
   break
 end
end

Ou vous pouvez utiliser la méthode + find + pour faire la même chose:

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.find {|item| item.include?("a")}
print result
OutputHammerhead

+ find + exécute le bloc que vous fournissez pour chaque élément du tableau. Si la dernière expression du bloc est évaluée à + ​​true +, la méthode + find + renvoie la valeur et arrête d’itérer. S’il ne trouve rien après avoir parcouru tous les éléments, il retourne + nil +.

La méthode + select + fonctionne de la même manière, mais elle construit un nouveau tableau contenant tous les éléments qui correspondent à la condition, au lieu de simplement renvoyer une valeur unique et de s’arrêter.

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
results = sharks.select {|item| item.include?("a")}
print results
Output["Hammerhead", "Great White", "Whale"]

La méthode + rejet + retourne un nouveau tableau contenant des éléments qui don’t ne correspondent pas à la condition. Vous pouvez le considérer comme un filtre qui supprime les éléments que vous ne souhaitez pas. Voici un exemple qui rejette toutes les entrées contenant la lettre + a +:

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
results = sharks.reject {|item| item.include?("a")}
print results
Output["Tiger"]

+ select + et + rejet + renvoient tous deux un nouveau tableau, laissant le tableau d’origine inchangé. Cependant, si vous utilisez les méthodes + select! + Et + rejet! +, Le tableau d’origine sera modifié.

La méthode + find_all + est un alias pour + select +, mais il n’y a pas de méthode + find_all! +.

Voyons ensuite comment trier les valeurs d’un tableau.

Tri d’un tableau

Le tri des données est une pratique courante. Vous devrez peut-être classer par ordre alphabétique une liste de noms ou trier les nombres du plus petit au plus grand.

Les tableaux Ruby ont une méthode + reverse + qui peut inverser l’ordre des éléments dans un tableau. Si vous avez une liste de données déjà organisée, + reverse + est un moyen rapide de retourner les éléments:

sharks = ["Angel", "Great White", "Hammerhead", "Tiger"]
reversed_sharks = sharks.reverse
print reversed_sharks
Output["Tiger", "Hammerhead", "Great White", "Angel"]

La méthode + reverse + renvoie un nouveau tableau et ne modifie pas l’original. Utilisez la méthode + reverse! + Si vous souhaitez plutôt modifier le tableau d’origine.

Cependant, inverser un tableau n’est pas toujours le moyen le plus efficace ni le plus pratique de trier les données. Utilisez la méthode + sort + pour trier les éléments d’un tableau comme vous le souhaitez.

Pour les tableaux simples de chaînes ou de nombres, la méthode `+ sort + 'est efficace et vous donnera les résultats que vous recherchez:

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort
print sorted_sharks
Output["Angel", "Great White", "Hammerhead", "Tiger"]

Cependant, si vous voulez trier les choses différemment, vous voudrez indiquer à la méthode + sort + comment procéder. La méthode + sort + prend un bloc Ruby qui vous donne accès aux éléments du tableau afin que vous puissiez les comparer.

Pour faire la comparaison, vous utilisez l’opérateur comparison (+ <⇒ +), souvent appelé opérateur spaceship. Cet opérateur compare deux objets Ruby et renvoie + -1 + si l’objet de gauche est plus petit, + 0 + si les objets sont identiques et + 1 + si l’objet de gauche est plus grand.

1 <=> 2    # -1
2 <=> 2    #  0
2 <=> 1    #  1

La méthode + sort + de Ruby accepte un bloc qui doit renvoyer + -1 +, + 0 + ou + 1 +, qu’il utilise ensuite pour trier les valeurs du tableau.

Voici un exemple qui compare explicitement les entrées du tableau à trier par ordre croissant:

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort{|a,b| a <=> b }
print sorted_sharks

Les variables + a + et + b + représentent des éléments individuels dans le tableau qui sont comparés. Le résultat ressemble à ceci:

Output["Angel", "Great White", "Hammerhead", "Tiger"]

Pour trier les requins dans l’ordre inverse, inversez les objets de la comparaison:

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort{|a,b| b <=> a }
print sorted_sharks
Output["Tiger", "Hammerhead", "Great White", "Angel"]

La méthode + sort + convient parfaitement aux tableaux contenant des types de données simples tels que des entiers, des flottants et des chaînes. Mais lorsque les tableaux contiennent des objets plus complexes, vous devrez faire un peu plus de travail.

Voici un tableau de hachages, chaque hachage représentant un requin:

sharks = [
 {name: "Hammerhead"},
 {name: "Great white"},
 {name: "Angel"}
]

Trier cela avec + sort n’est pas aussi facile. L’appel de + sort + sur le tableau échoue:

sharks.sort
OutputArgumentError: comparison of Hash with Hash failed

Pour faire la comparaison, nous devons dire + sort + ce que nous voulons comparer. Nous allons donc comparer les valeurs de la clé +: name + dans le hachage:

sorted_sharks.sort{|a, b| a[:name] <=> b[:name]}
print sorted_sharks
Output[{:name=>"Angel"}, {:name=>"Great white"}, {:name=>"Hammerhead"}]

Lorsque vous travaillez avec des structures plus complexes, vous voudrez peut-être plutôt utiliser la méthode + sort_by +, qui utilise un algorithme plus efficace pour le tri. + sort_by + prend un bloc qui ne nécessite qu’un seul argument, la référence à l’élément actuel du tableau:

sharks = [
 {name: "Hammerhead"},
 {name: "Great white"},
 {name: "Angel"}
]

sorted_sharks = sharks.sort_by{|shark| shark[:name] }
print sorted_sharks
Output[{:name=>"Angel"}, {:name=>"Great white"}, {:name=>"Hammerhead"}]

La méthode + sort_by + implémente une transformation Schwartzian, un algorithme de tri plus approprié pour comparer des objets en fonction de la valeur d’une clé spécifique. Par conséquent, vous utiliserez + sort_by + lorsque vous comparez des collections d’objets, car c’est plus efficace.

+ Sort + et + sort_by + renvoient tous deux de nouveaux tableaux, laissant le tableau d’origine intact. Si vous souhaitez modifier le tableau d’origine, utilisez plutôt + sort! + Et + sort_by! +.

Outre le tri des valeurs, vous pouvez également vous débarrasser des doublons.

Supprimer des éléments en double

Parfois, vous obtiendrez des listes de données dupliquées. Vous pouvez parcourir le tableau et filtrer les doublons, mais la méthode + uniq + de Ruby facilite grandement les choses. La méthode + uniq + renvoie un nouveau tableau avec toutes les valeurs en double supprimées.

[1,2,3,4,1,5,3].uniq   # [1,2,3,4,5]

Parfois, lorsque vous fusionnez deux ensembles de données, vous obtenez des doublons. Prenez ces deux tableaux de requins:

sharks = ["Tiger", "Great White"]
new_sharks = ["Tiger", "Hammerhead"]

Si nous les additionnons, nous aurons une entrée en double:

sharks + new_sharks
# ["Tiger", "Great White", "Tiger", "Hammerhead"]

Vous pouvez utiliser + uniq + pour supprimer les doublons, mais il vaut mieux éviter de les introduire entièrement. Au lieu d’ajouter les tableaux, utilisez l’opérateur de pipe` + | + `, qui fusionne les tableaux:

sharks | new_sharks
# ["Tiger", "Great White", "Hammerhead"]

Les tableaux Ruby prennent également en charge la soustraction, ce qui signifie que vous pouvez soustraire + new_sharks + de + sharks + pour obtenir uniquement les nouvelles valeurs:

sharks = ["Tiger", "Great White"]
new_sharks = ["Tiger", "Hammerhead"]
sharks - new_sharks   # ["Great White"]

Voyons ensuite comment manipuler la valeur de chaque élément.

Transformer les données

La méthode + map +, et son alias + collect +, peuvent transformer le contenu du tableau, ce qui signifie qu’elle peut effectuer une opération sur chaque élément du tableau.

Par exemple, vous pouvez utiliser + map + pour effectuer une arithmétique sur chaque entrée d’un tableau et créer un nouveau tableau contenant les nouvelles valeurs:

numbers = [2,4,6,8]

# square each number
squared_numbers = numbers.map {|number| number * number}

print squared_numbers

La variable + squared_numbers + est un tableau des nombres d’origine, au carré:

[4, 16, 36, 64]

+ map + est souvent utilisé dans les applications Web pour transformer un tableau en éléments pour une liste déroulante HTML. Voici une version très simplifiée de ce à quoi cela pourrait ressembler:

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]

options = sharks.map {|shark| "<option>#{shark}</option>"}

print options

Le tableau + options + a maintenant chaque requin enveloppé dans la balise HTML + <option> </ option> +:

["<option>Hammerhead</option>", "<option>Great White</option>", "<option>Tiger</option>", "<option>Whale</option>"]

+ map + renvoie un nouveau tableau, laissant le tableau d’origine non modifié. Utiliser + map! + Modifierait le tableau existant. Et rappelez-vous que + map + a un alias appelé` + collect + `. Vous devez être cohérent et utiliser l’un ou l’autre dans votre code.

Puisque + map + renvoie un nouveau tableau, celui-ci peut ensuite être transformé et modifié, voire converti en chaîne. Voyons cela ensuite.

Conversion d’un tableau en chaîne

Tous les objets de Ruby ont une méthode + to_s +, qui convertit l’objet en chaîne. C’est ce que l’instruction + print + utilise. Étant donné notre gamme de + requins +:

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]

L’appel de la méthode + to_s + crée cette chaîne:

"[\"Hammerhead\", \"Great White\", \"Tiger\", \"Whale\"]"

C’est excellent pour le débogage, mais ce n’est pas très utile dans un vrai programme.

La méthode + join + convertit un tableau en chaîne, mais vous donne beaucoup plus de contrôle sur la combinaison des éléments. La méthode + join + prend un argument spécifiant le caractère que vous voulez utiliser comme séparateur. Pour transformer le tableau de requins en une chaîne de noms de requins séparés par des espaces, procédez comme suit:

shark_join.rb

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join(" ")
print result
OutputHammerhead Great White Tiger Whale

Si vous voulez que chaque nom de requin soit séparé par une virgule et un espace, utilisez une virgule et un espace comme délimiteur:

shark_join.rb

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join(", ")
print result
OutputHammerhead, Great White, Tiger, Whale

Si vous ne spécifiez pas d’argument dans la méthode `+ join + ', vous obtiendrez toujours une chaîne, mais elle n’aura pas de délimiteur:

shark_join.rb

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join
print result
OutputHammerheadGreat WhiteTigerWhale

Utiliser + join + en conjonction avec + map + est un moyen rapide de transformer un tableau de données en sortie. Utilisez + map + pour transformer chaque élément des données, puis + join + pour transformer le tout en une chaîne que vous pouvez imprimer. Vous souvenez-vous de notre exemple de transformation de notre tableau + sharks + en un tableau d’éléments HTML? Voici à nouveau le même exemple, mais cette fois-ci, nous utiliserons + join + pour convertir le tableau d’éléments en une chaîne avec des caractères de nouvelle ligne comme séparateur:

map.rb

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
options = sharks.map {|shark| "<option>#{shark}</option>"}
output = options.join("\n")
print output
Output<option>Hammerhead</option>
<option>Great White</option>
<option>Tiger</option>
<option>Whale</option>

Au lieu de convertir un tableau en chaîne, vous souhaiterez peut-être obtenir le total de son contenu ou effectuer un autre type de transformation permettant d’obtenir une valeur unique. C’est à côté.

Réduire les tableaux à une valeur unique

Lorsque vous travaillez avec un ensemble de données, vous pouvez être amené à regrouper les données dans une valeur unique, telle qu’une somme. Une façon de faire est d’utiliser une variable et la méthode + each +:

result = 0
[1, 2, 3].each {|num| result += num}
print result
Output6

Vous pouvez utiliser la méthode + reduction + pour le faire à la place. La méthode reduction + effectue une itération sur un tableau et conserve un total cumulé en exécutant une opération binaire pour chaque élément.

La méthode + réduction + accepte une valeur initiale pour le résultat, ainsi qu’un bloc avec deux valeurs locales: une référence au résultat et une référence à l’élément en cours. À l’intérieur du bloc, vous spécifiez la logique pour calculer le résultat final.

Puisque nous voulons résumer le tableau, nous allons initialiser le résultat à + ​​0 + puis ajouter la valeur actuelle au résultat dans le bloc:

output = [1,2,3].reduce(0) {|result, current| result += current }
print output
Output6

Si vous envisagez d’initialiser le résultat sur + 0 +, vous pouvez omettre l’argument et simplement passer le bloc. Cela définira automatiquement le résultat sur la première valeur du tableau:

output = [1,2,3].reduce {|result, current| result += current }
print output
Output6

La méthode + réduction + vous spécifie également une méthode _binary, ou une méthode sur un objet qui accepte un autre objet en tant qu’argument, qu’elle exécutera pour chaque entrée du tableau. + reduction + utilise ensuite les résultats pour créer une valeur unique.

Lorsque vous écrivez +2 + 2 + dans Ruby, vous appelez en fait la méthode + sur l’entier + 2 +:

2.+(2)   # 4

Ruby utilise du sucre _syntactique afin que vous puissiez l’exprimer par +2 + 2 +.

La méthode + réduire + vous permet de spécifier une méthode binaire en lui donnant son nom sous forme de symbole. Cela signifie que vous pouvez passer : + à la méthode + reduction + pour résumer le tableau:

output = [1, 2, 3].reduce(:+)
print output
Output6

Vous pouvez utiliser + reduction + pour faire plus que simplement additionner des listes de nombres. Vous pouvez l’utiliser pour transformer des valeurs. Rappelez-vous que + reduction + réduit un tableau à une valeur unique. Mais aucune règle ne dit qu’une valeur unique ne peut pas être un autre tableau.

Disons que nous avons une liste de valeurs que nous devons convertir en nombres entiers. mais nous voulons seulement les valeurs qui peuvent être converties en entiers.

Nous pourrions utiliser + rejette pour supprimer les valeurs non numériques, puis utiliser` + map` pour convertir les valeurs restantes en entiers. Mais nous pouvons tout faire en une seule étape avec + reduction +. Voici comment.

Utilisez un tableau vide comme valeur d’initialisation. Ensuite, dans le bloc, convertissez la valeur actuelle en Integer avec la méthode + Integer +. Si la valeur ne peut pas être convertie en Integer, + Integer + lève une exception, que vous pouvez intercepter et affecter + nil + à la valeur.

Ensuite, prenez la valeur et mettez-la dans le tableau, mais seulement si ce n’est pas + nil +.

Voici à quoi ressemble le code. Essayez ceci:

convert_array_of_values.rb

values = ["1", "2", "a", "3"]
integers = values.reduce([]) do |array, current|
 val = Integer(current) rescue nil
 array.push(val) unless val.nil?
 array
end
print integers
Output[1,2,3]

Chaque fois que vous avez une liste d’éléments que vous devez convertir en une seule valeur, vous pourrez peut-être la résoudre avec + reduction +.

Conclusion

Dans ce tutoriel, vous avez utilisé plusieurs méthodes pour travailler avec des tableaux. Vous avez saisi des éléments individuels, récupéré des valeurs en effectuant une recherche dans le tableau, trié des éléments, puis transformé les données en créant de nouveaux tableaux, chaînes et totaux. Vous pouvez appliquer ces concepts à la résolution de nombreux problèmes de programmation courants avec Ruby.

Veillez à consulter ces didacticiels connexes pour continuer à explorer comment utiliser les données dans Ruby: