Ruby: Object.to_a замена

Мне нужно преобразовать передаваемый аргумент (один объект или коллекцию) в массив. Я не знаю, в чем аргумент. Если это уже массив, я хочу оставить его, в противном случае создать массив из одного элемента. Я ищуразрешить обаmethod(:objs => obj) а такжеmethod(:objs => [obj1, obj2])

Кажется, это лучший способ (Array # to_a возвращает self):

arg = arg.to_a

Но рубиновые документы говорятObject#to_a скоро устареет, Есть ли удобная замена?

Что-нибудь более краткое, чем это?

arg = arg.respond_to?(:to_a) ? arg.to_a : [arg]

Ответы на вопрос(7)

Я не уверен, помогает ли это, но мне часто нужно не то, чтобы arg был массивом, а то, что arg отвечает каждому.

arg = [arg] unless arg.respond_to? :each
 Andrew Marshall12 апр. 2012 г., 09:57
Многие вещи, которые не являются массивом, отвечают наeach.

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

[:[], :each, :etc...].all? { |m| obj.respond_to? m } ? obj : [obj]

Преимущество состоит в том, что вы даете объекту возможность реализовать собственную семантику для индексированного доступа.

Ух ты, кто-то некроманировал действительно старую нить. : -O Но так как я пока не вижу его включенным, я добавлю еще один способ для полноты картины:

arg = [*arg]

Это приведет к появлению аргумента, если он уже является массивом (таким образом, удаляется один уровень вложенности) или в противном случае будет создан массив с одним аргументом:

arg = [1,2,3]
[*arg] #=> [1, 2, 3]
arg = 1
[*arg] #=> [1]
 Ivan Olshansky13 мар. 2019 г., 19:48
Фактически, он возвращает тот же результат, что иArray(), Например:[*nil] =>[], [*{a: 'a', b: 'b'}] =>[[:a, "a"], [:b, "b"]]
 microspino12 апр. 2013 г., 11:53
как всегда ты великолепен!

Кажется толькоObject.to_a устарела, удаляя значение по умолчаниюto_a и заставляя каждый класс определять свой собственный (например,Hash.to_a).

self.to_a       #=> -:1: warning: default `to_a' will be obsolete
"hello".to_a    #=> ["hello"]
Time.new.to_a   #=> [39, 54, 8, 9, 4, 2003, 3, 99, true, "CDT"]

h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300  }
h.to_a   #=> [["a", 100], ["c", 300], ["d", 400]]

Если ваш аргумент является экземпляромObject, пытаться:

Hash.new(obj).to_a

@Daniel [комментарий к Олливье]:Дело в том, что я не знаю, что это за аргумент. Если это уже массив, я хочу оставить его, в противном случае создать массив из одного элемента.

Если это так, попробуйте:

obj = [obj] if !obj.is_a?(Array)
 Jonathan Lonowski22 дек. 2008 г., 12:52
Нету. Просто никогда не использовал это раньше. Все еще немного зеленый с Руби. ;)
 Yaser Sulaiman22 дек. 2008 г., 12:35
obj = [obj] разве что obj.is_a? (Array) может быть легче читать ... если, конечно, вам не нравится "разве что"!
 Daniel Beardsley22 дек. 2008 г., 12:03
Не совсем то, что я искал, и Hash.new (obj) .to_a всегда возвращает [].

А как насчет Array.new (1, arg)?

 Daniel Beardsley22 дек. 2008 г., 11:54
Дело в том, что я не знаю, что это за аргумент. Если это уже массив, я хочу оставить его, в противном случае создать массив из одного элемента.
Решение Вопроса

Используйте методЯдро # Массив:

Array([1,2,3]) #=> [1, 2, 3]
Array(123) #=> [123]

Да, сначала это может выглядеть как класс, но на самом деле это метод, который начинается с заглавной буквы.

 Daniel Beardsley22 дек. 2008 г., 20:18
Отлично! Именно то, что я искал.
 glenn mcdonald23 дек. 2008 г., 05:34
Однако следует помнить пару вещей: 1) Если вы передадите хэш Array (), вы получите hash.to_a, а не [hash]. 2) Если вы передадите nil Array (), вы получите [], а не [nil].
 Dan Rosenstark24 мая 2010 г., 16:26
Нет, подождите, это было неправильно. Извините, это так ясно в документах. Это вызываетto_a... О, вот оно из 1.9 "Возвращает arg как массив. Сначала пытается вызвать arg.to_ary, затем arg.to_a." WTF ?????
 triskweline26 июл. 2010 г., 13:41
Просто чтобы быть понятным, оба nil.to_a и Array (nil) возвращают пустой массив.
 Dan Rosenstark24 мая 2010 г., 16:22
Руби это так круто. Все является объектом. Я имею в виду, иногда. Ну, Кернел, это объект, и на нем тоже есть несколько объектных методов с заглавными буквами! Так что жеKernel.Array в любом случае? О да, это называетсяto_ary метод на объекте. Если это не сработает, он помещает ваш параметр в одноэлементный массив. Tricky!

Я делаю это много и всегда использую:

arg = [arg] unless arg.is_a?(Array)

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

arg = [arg].flatten
 Max DeLiso13 июл. 2013 г., 05:57
это лучшее и наиболее явное решение, никаких странных угловых случаев с хешами или нулем.

Ваш ответ на вопрос