J'ai construit cette méthode pour trouver le mot le plus long dans un tableau, mais je me demande s'il y a une meilleure façon de l'avoir fait. Je suis plutôt nouveau à Ruby, et je fais juste cela comme un exercice d'apprentissage de la méthode code> injecter code>.
Il renvoie le mot le plus long dans une matrice ou un tableau des mots les plus longs égaux. p>
6 Réponses :
Ruby a une méthode standard pour renvoyer un élément dans une liste avec le maximum d'une valeur. ou vous pouvez utiliser la méthode max_by p> pour obtenir tous les éléments avec la longueur maximale p>
C'est bien, mais l'OP "a juste fait cela comme un exercice d'apprentissage de la méthode d'injecte."
Les deux méthodes renvoient uniquement un seul élément, pas un tableau de certaines cordes tout aussi longues.
une doublure à deux: ou si vous voulez utiliser l'injection, cela utilise votre idée, mais c'est plus court. P> test_array.inject{ |ret,word|
ret = [ret] unless ret.kind_of?(Array)
ret << word if word.size == ret.first.size
ret = [word] if word.size > ret.first.size
ret
}
Cette méthode n'est pas idempotente lorsqu'elle est appliquée directement sur un tableau. Probablement pas ce que vous attendez. Vous pouvez utiliser un clone code> ici. Mais la solution est correcte et probablement même pas la plus lente (sans connaître les détails de la mise en œuvre de la méthode intégrée
GROUP_BY CODE>)
@Holger: group_by code> utilise des recherches de tableau, donc c'est fondamentalement
o (n) code>, tandis que le tri code> est plus lent.
Au lieu de delete_if code>, vous pouvez utiliser
Take_whIle code> qui s'arrête dès qu'il atteint un mot plus petit.
module Enumerable def longest_word (strings = map(&:to_s)). zip(strings.map(&:length)). inject([[''],0]) {|(wws, ll), (w, l)| case l <=> ll when -1 then [wws, ll] when 1 then [[w], l] else [wws + [w], ll] end }.first end end This method only depends on generic Enumerable methods, there's nothing Array specific about it, therefore we can pull it up into the Enumerable module, where it will also be available for Sets or Enumerators, not just Arrays.
Cela renvoie un seul élément, pas un éventail de mots avec des tailles égales.
@steenslag: Ouais, merci d'avoir remarqué. Le nom de la méthode m'a jeté un peu, j'aurais attendu une méthode qui retourne plusieurs mots à appeler longest_words code> (pluriel).
Je ferais
class Array def longest_word group_by(&:size).max.last end end
Si vous êtes sûr que vous n'avez que des chaînes, vous pouvez l'écrire comme self.group_by (& longueur) .max.last code> sinon vous auriez besoin d'un
additionnel code> appel comme
Self.group_by {| el | el.to_s.Size} .max.last code>. Et enfin, pour renvoyer une seule chaîne lorsque vous n'avez qu'un seul élément, vous pouvez faire
longest_word.size> 1? Longest_word: longest_word.first code> avant de revenir.
Joli! J'ai pris la liberté de faire le code plus concis, mais s'il vous plaît revenir si vous n'aimez pas le style
L'OP a dit dans la question qu'il a fait cela afin d'apprendre injecter code>, et il n'est pas tout à fait clair s'il cherchait une meilleure façon d'utiliser
injecter code> ou juste une meilleure façon période. Le vôtre est une jolie réponse à la deuxième interprétation et @mladen Jablanović à la première. Les deux obtiennent mon +1.
Cela a commencé avec moi avec moi jouant avec injecter code>, mais voyant qu'il y a des moyens plus courts de le faire sans cette méthode est intéressante. Merci!
@ Marc-André Lafortune Il est beaucoup plus lisible de cette façon, merci.
Vous voudrez peut-être vérifier cela aussi Lien
@Inlamazab min_by code> (et
max_by code>) renvoie une seule valeur, celle-ci renvoie un tableau avec une ou plusieurs valeurs.
@steenslag Depuis que je vous ai vu avoir seulement la dernière valeur, je pensais que mentionner l'autre réponse en vaut la peine. Merci pour l'indice.
Voici un en utilisant injecter code> (ne fonctionne pas pour un tableau vide):
words.inject(['']){|a,w|
[a + [w], [w], a][w.length <=> a.last.length]
}
En fait, ce devrait i> travailler pour un tableau vide, c'est-à-dire (un) du (s) point (s) d'alimenter explicitement une valeur initiale pour l'accumulateur.
Dans ma version, je pensais en quelque sorte qu'il serait beaucoup plus propre de enfiler les longueurs de mots implicitement à travers l'accumulateur, mais cela n'a pas beaucoup nettoyé beaucoup :-) Vous avez l'air beaucoup plus agréable.
Afin de travailler pour des tableaux vides, il faudrait reculer injecter code> avec un tableau vide (plutôt qu'un tableau contenant une chaîne vide comme je le fais) et compliquer la ramification à l'intérieur d'un peu plus. Mais à des fins d'apprentissage
injecter code>, je pensais que c'était suffisant.
Ah, oui, cela rendra un mauvais résultat. Je pensais plus sur Haskell, où plipl1 code> lancera une erreur lorsque
FLETL code> ne sera pas ou ma solution qui appelle
premier code> à la suite de Le
injecter code>, qui serait
nil code> pour un tableau vide sans un accumulateur initial explicite et augmentez ainsi un
nométhoderror code>. (Je devrais apprendre à ne pas répondre à des questions ou laissez des commentaires dans une précipitation, avec ma veste sur, littéralement à mi-chemin de la porte :-))
Cette solution utilise la méthode d'injection pour accumuler les cordes les plus longues dans une matrice, puis les ramasse avec la longueur la plus élevée. P>
animaux = ["souris", "chat", "oiseau", "ours", "orose"] p>
animaux.Inject (hash.new {| h, k | h [k] = []}) {| ACC, E | ACC [E.SIZE] << e; ACC} .sort.Last [1] P>
Ce retour: ["souris", "souris"] p>