Façon correcte de remplir un tableau avec une plage en Ruby

202

Je travaille sur un livre qui donne des exemples de plages converties en tableaux équivalents en utilisant leurs méthodes "to_a"

Lorsque j'exécute le code dans irb, j'obtiens l'avertissement suivant

 warning: default `to_a' will be obsolete

Quelle est la bonne alternative à l'utilisation de to_a?

existe-t-il d'autres façons de remplir un tableau avec une plage?

Willbill
la source
7
La grande mise en garde pour convertir une plage en tableau, est qu'une grande plage peut consommer beaucoup de mémoire lorsque le tableau est construit, alors utilisez-le avec précaution. Au lieu de créer le tableau, il peut être préférable d'itérer sur la plage comme vous le feriez pour un tableau afin de réduire la consommation de mémoire. C'est une de ces choses "appliquer au besoin".
The Tin Man

Réponses:

358

Vous pouvez créer un tableau avec une plage en utilisant splat,

>> a=*(1..10)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

en utilisant la Kernel Arrayméthode,

Array (1..10)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

ou en utilisant to_a

(1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Zamith
la source
1
Et si le tableau est déjà créé et que vous souhaitez y ajouter une plage: je l'ai order = 1. Alors order << (2.25).to_a. Mais cela crée un autre tableau à l'intérieur du tableau, je veux simplement la plage de 2 à 25. Pourtant, si j'essaye, order << (2.25)j'obtiens l'erreur ne peut pas convertir Range en entier.
kakubei
1
@kakubei utilise concatau lieu de <<. De plus, vous ne devriez pas obtenir "impossible de convertir la plage en nombre entier" à moins qu'il ne s'agisse d' orderun entier - auquel cas vous seriez en train de changer de bit, pas d'ajouter un tableau.
Kelvin
3
l'option Splat ne fonctionne pas pour Ruby 1.8.7, je recommanderais d'utiliser (1..10).to_apour la compatibilité descendante
kylewelsby
5
Votre utilisation de splat est désagréable. Une meilleure option est [*1..10].
Hauleth
2
quel est le moyen le plus rapide ??
Andrey Yasinishyn
79

Cela fonctionne pour moi dans irb:

irb> (1..4).to_a
=> [1, 2, 3, 4]

Je remarque que:

irb> 1..4.to_a
(irb):1: warning: default `to_a' will be obsolete
ArgumentError: bad value for range
        from (irb):1

Alors peut-être que vous manquez les parenthèses?

(J'utilise Ruby 1.8.6 patchlevel 114)

Daniel Lucraft
la source
7
Explication : sans la parenthèse, vous appelez la méthode to_a à partir d'une instance de la classe Fixnum (dans ce cas 4), pas sur la plage 1..4. Si vous exécutez Fixnum.methods.include?(to_a)dans ruby ​​1.9.2, vous remarquerez que la méthode to_a n'est plus définie, d'où la raison pour laquelle vous receviez ce message de dépréciation en 08
Pierre
@Pierre Je pense que vous vouliez direFixnum.instance_methods.include?(:to_a)
Kelvin
@Kelvin - En fait, methods.include?c'est plus informatif: $ irb irb(main):001:0> Fixnum.methods.include?(to_a) (irb):1: warning: default to_a 'sera obsolète=> false irb(main):002:0> Fixnum.instance_methods.include?(:to_a) => false
Richard Turner
1
@RichardTurner Je suppose que vous utilisez ruby ​​1.8. Je crains que vous ne compreniez mal ce qui déclenche l' to_aavertissement dans la première forme. C'est parce que vous appelez to_ale self- vous ne vérifiez pas réellement si to_aest une méthode de Fixnum. Essayez d'appeler to_apar lui-même et vous verrez le même avertissement.
Kelvin
@Kelvin - Duh! Le sou tombe. Merci.
Richard Turner
34

On dirait que tu fais ça:

0..10.to_a

L'avertissement provient de Fixnum # to_a, et non de Range # to_a. Essayez plutôt ceci:

(0..10).to_a
Richard Turner
la source
9

Vérifie ça:

a = [*(1..10), :top, *10.downto( 1 )]
Boris Stitnicky
la source
2
Le * 10.downto (1) était ce que je cherchais, merci!
Daniel
6

C'est une autre façon:

irb> [*1..10]

=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Jesús Andrés Valencia Montoya
la source
4

J'ai juste essayé d'utiliser des plages allant de plus grandes à plus petites et j'ai obtenu le résultat auquel je ne m'attendais pas:

irb(main):007:0> Array(1..5)
=> [1, 2, 3, 4, 5]
irb(main):008:0> Array(5..1)
=> []

C'est à cause des implémentations de plages.
J'ai donc dû utiliser l'option suivante:

(1..5).to_a.reverse
Nickolay Kondratenko
la source
4
Aujourd'hui, j'ai découvert 5.downto(1).to_aune autre façon d'exprimer une plage décroissante stackoverflow.com/a/8927009/703903
odlp