Правильный способ заполнения массива с помощью Range в Ruby

202

Я работаю над книгой, в которой приводятся примеры преобразования диапазонов в эквивалентные массивы с использованием их методов "to_a"

Когда я запускаю код в IRB, я получаю следующее предупреждение

 warning: default `to_a' will be obsolete

Какова правильная альтернатива использованию to_a?

Существуют ли альтернативные способы заполнения массива Range?

Willbill
источник
7
Большое предостережение о преобразовании диапазона в массив - большой диапазон может потреблять много памяти при построении массива, поэтому используйте его с осторожностью. Вместо создания массива может быть лучше выполнить итерации по диапазону, как если бы вы использовали массив, чтобы снизить потребление памяти. Это одна из тех вещей, которые «применяются по мере необходимости».
Жестянщик

Ответы:

358

Вы можете создать массив с диапазоном, используя сплат,

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

используя Kernel Arrayметод,

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

или используя to_a

(1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Zamith
источник
1
Что делать, если массив уже создан, и вы хотите добавить диапазон к нему: у меня есть order = 1. Потом order << (2.25).to_a. Но это создает другой массив внутри массива, я просто хочу диапазон от 2 до 25. Тем не менее, если я пытаюсь order << (2.25)получить ошибку, я не могу преобразовать Range в Integer.
Какубей
1
@kakubei использовать concatвместо <<. Кроме того, вы не должны получать сообщение «не можете преобразовать Range в Integer», если orderэто не целое число - в этом случае вы будете сдвигать биты, а не добавлять массив.
Кельвин
3
опция Splat не работает для Ruby 1.8.7, я бы порекомендовал использовать (1..10).to_aдля обратной совместимости
kylewelsby
5
Вы используете сплат противно. Лучший вариант выглядит [*1..10].
Хаулет
2
какой самый быстрый способ ??
Андрей Ясинишин
79

Это работает для меня в IRB:

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

Я замечаю, что:

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

Так что, возможно, вам не хватает скобок?

(Я использую Ruby 1.8.6 уровня исправления 114)

Даниэль Люкрафт
источник
7
Объяснение : без скобок вы вызываете метод to_a из экземпляра класса Fixnum (в данном случае 4), а не из диапазона 1..4. Если вы запустите Fixnum.methods.include?(to_a)ruby 1.9.2, вы заметите, что метод to_a больше не определен, поэтому вы получили это сообщение об амортизации в 08
Pierre
@Pierre Я думаю, что вы имели в видуFixnum.instance_methods.include?(:to_a)
Кельвин
@Kelvin - На самом деле, methods.include?более информативно: $ irb irb(main):001:0> Fixnum.methods.include?(to_a) (irb):1: warning: default to_a 'будет устаревшим=> false irb(main):002:0> Fixnum.instance_methods.include?(:to_a) => false
Ричард Тернер
1
@RichardTurner Полагаю, вы используете ruby ​​1.8. Боюсь, вы неправильно понимаете, что вызывает to_aпредупреждение в первой форме. Это потому , что вы звоните to_aна self- вы на самом деле не проверки , является ли to_aэто метод Fixnum. Попробуйте позвонить to_aсамостоятельно, и вы увидите то же самое предупреждение.
Кельвин
@ Кельвин - Дух! Пенни падает. Спасибо.
Ричард Тернер
34

Похоже, вы делаете это:

0..10.to_a

Предупреждение от Fixnum # to_a, а не от Range # to_a. Попробуйте это вместо этого:

(0..10).to_a
Ричард Тернер
источник
9

Проверь это:

a = [*(1..10), :top, *10.downto( 1 )]
Борис Стиницкий
источник
2
* 10. downto (1) было то, что я искал, спасибо!
Даниил
6

Это еще один способ:

irb> [*1..10]

=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Хесус Андрес Валенсия Монтойя
источник
4

Я просто попытался использовать диапазоны от большего к меньшему количеству и получил результат, которого я не ожидал:

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

Это из-за реализации диапазонов.
Поэтому мне пришлось использовать следующую опцию:

(1..5).to_a.reverse
Николай Кондратенко
источник
4
Сегодня я обнаружил, 5.downto(1).to_aчто это еще один способ выражения уменьшающегося диапазона stackoverflow.com/a/8927009/703903
odlp