Ruby: Object.to_a замена - PullRequest
       23

Ruby: Object.to_a замена

27 голосов
/ 22 декабря 2008

Мне нужно преобразовать переданный аргумент (отдельный объект или коллекцию) в массив. Я не знаю, в чем аргумент. Если это уже массив, я хочу оставить его, в противном случае создать массив из одного элемента. Я смотрю разрешить как 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 ]

45 голосов
/ 22 декабря 2008

Используйте метод Kernel # Array :

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

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

9 голосов
/ 22 июля 2011

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

arg = [*arg]

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

arg = [1,2,3]
[*arg] #=> [1, 2, 3]
arg = 1
[*arg] #=> [1]
2 голосов
/ 22 декабря 2008

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

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

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

arg = [arg].flatten
2 голосов
/ 22 декабря 2008

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

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

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

2 голосов
/ 22 декабря 2008

Кажется, только 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

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

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

obj = [obj] if !obj.is_a?(Array)
1 голос
/ 22 декабря 2008

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

arg = [arg] unless arg.respond_to? :each
0 голосов
/ 22 декабря 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...