128 votes

Y a-t-il une raison pour laquelle nous ne pouvons pas itérer sur "reverse Range" en ruby?

J'ai essayé d'itérer à l'envers avec ruby en utilisant une gamme et chacun. Par ici:

 (4..0).each do |i|
  puts i
end
==> 4..0
 

L'itération à 0..4 écrit les nombres. Par ailleurs, r = 4..0 semble être correct, r.first == 4, r.last == 0. Cela me semble étrange que la construction ci-dessus ne produise pas le résultat attendu. Quelle est la raison de cela? Quelles sont les situations où ce comportement est raisonnable?

119voto

John Feminella Points 116878

Une plage est juste que: quelque chose de défini par son début et à la fin, non pas par son contenu. "Itération" sur une plage n'a pas vraiment de sens que dans un cas général. Considérons, par exemple, la façon de les "itérer" plus de la gamme produite par deux dates. Souhaitez-vous effectuer une itération par jour? par mois? par an? par semaine? Ce n'est pas bien défini. OMI, le fait qu'il est permis pour les plages doit être considérée comme une méthode de convenance uniquement.

Si vous souhaitez effectuer une itération vers l'arrière sur une plage comme ça, vous pouvez toujours utiliser downto:

$ r = 10..6
=> 10..6

$ (r.first).downto(r.last).each { |i| puts i }
10
9
8
7
6

Voici quelques idées des autres, raison pour laquelle il est difficile de les deux permettent d'itération et constamment gérer inverse des plages.

108voto

Marko Taponen Points 416

Que diriez-vous de (0..1).reverse_each qui itère la plage en arrière?

19voto

Jonas Elfström Points 16453

En itérant sur une plage en Ruby avec each la méthode succ appelée sur le premier objet de la plage.

 $ 4.succ
=> 5
 

Et 5 est en dehors de la plage.

Vous pouvez simuler une itération inverse avec ce hack:

 (-4..0).each { |n| puts n.abs }
 

John a fait remarquer que cela ne fonctionnerait pas s'il couvrait 0. Cela:

 >> (-2..2).each { |n| puts n*-1 }
2
1
0
-1
-2
=> -2..2
 

Je ne peux pas dire que j'aime vraiment aucun d'entre eux parce qu'ils obscurcissent en quelque sorte l'intention.

15voto

Sergey Kishenin Points 3118

Une autre façon est (1..10).to_a.reverse

12voto

bta Points 22525

Selon le livre "Programmation Ruby", l'objet de la Plage stocke les deux extrémités de la gamme et utilise l' .succ membre pour générer les valeurs intermédiaires. En fonction du type de type de données que vous utilisez dans votre gamme, vous pouvez toujours créer une sous-classe de Integer et re-définir l' .succ membre de sorte qu'il agit comme un itérateur inverse (vous auriez probablement aussi à re-définir .next ).

Vous pouvez également obtenir les résultats que vous cherchez sans l'aide d'une Fourchette. Essayez ceci:

4.step(0, -1) do |i|
    puts i
end

Ce sera l'étape de 4 à 0 par pas de -1. Cependant, je ne sais pas si cela va fonctionner pour tout sauf pour les arguments Entiers.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X