Ответ 1
Используйте метод Kernel # Array:
Array([1,2,3]) #=> [1, 2, 3]
Array(123) #=> [123]
Да, он может сначала выглядеть как класс, но на самом деле это метод, начинающийся с заглавной буквы.
Мне нужно преобразовать переданный аргумент (отдельный объект или коллекцию) в массив. Я не знаю, что такое аргумент. Если это уже массив, я хочу оставить его, иначе создайте из него одноэлементный массив. Я ищу разрешить как 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]
Используйте метод Kernel # Array:
Array([1,2,3]) #=> [1, 2, 3]
Array(123) #=> [123]
Да, он может сначала выглядеть как класс, но на самом деле это метод, начинающийся с заглавной буквы.
Ничего себе, кто-то просто некроментировал действительно старую нить.: -O Но, поскольку я еще не вижу его включенным, я добавлю еще один способ для полноты:
arg = [*arg]
Это разделит аргумент, если он уже является массивом (таким образом, удалив один уровень вложенности) или создайте массив с одним аргументом иначе:
arg = [1,2,3]
[*arg] #=> [1, 2, 3]
arg = 1
[*arg] #=> [1]
Кажется, что только 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)
Вы можете взять apache для утки, если это лучше подходит для этой проблемы, составить список всех необходимых вам методов и проверить, есть ли у них объект, если нет, сделать его массивом:
[:[], :each, :etc...].all? { |m| obj.respond_to? m } ? obj : [obj]
Преимущество заключается в том, что вы даете объекту возможность реализовать свою собственную семантику для индексированного доступа.
Я не уверен, помогает ли это, но то, что мне часто нужно, - это не то, что arg является массивом, а то, что arg отвечает каждому.
arg = [arg] unless arg.respond_to? :each
Я делаю это много и всегда использую:
arg = [arg] unless arg.is_a?(Array)
Хотя, если вы знаете, что вы никогда не передаете массивы в виде индивидуальных аргументов, вы также можете:
arg = [arg].flatten
Как насчет Array.new(1, arg)?