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?


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]

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)


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



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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.