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


202

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

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

 warning: default `to_a' will be obsolete

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

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


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]

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



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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.