Принятие параметра как отдельного объекта или как массива объектов - PullRequest
10 голосов
/ 28 февраля 2012

У меня есть набор функций, которые принимают либо массив объектов, либо отдельный объект, предназначенный для обработки как массив, содержащий один объект, и я ищу более чистый способ сделать это.В общем, я хочу знать, как я могу сделать деталь unless в следующей функции более краткой:

def foo(bar_or_bars)
  unless bar_or_bars.is_a?(Array)
    bar_or_bars = [bar_or_bars]
  end
  bar_or_bars.each { |baz| ... }
end

Любая помощь будет оценена по достоинству!Спасибо.

Ответы [ 3 ]

21 голосов
/ 01 марта 2013

Самое чистое решение, которое я нашел, это использование метода ядра Array:

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

, так что

def foo(bar_or_bars)
  bars = Array(bar_or_bars)
  bars.each { |baz| ... }

Это будет работать даже на вложенных массивах, которые имеют массивы в качестве элементов (они небыть расплющенным)

13 голосов
/ 28 февраля 2012

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

bars = bar_or_bars.is_a?(Array) ? bar_or_bars : [bar_or_bars]

Как видите, я даю ему новое имя здесь, так как оно больше не является полосой или полосойтеперь это определенно коллекция.

Проблема с этим и вашим оригинальным подходом заключается в том, что хотя ваша функция может работать на любом Enumerable, вы заставите своих пользователей дать вам аргумент определенного типа, который* * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *.Это на самом деле пахнет как плохой дизайн API.Вероятно, вам лучше принять несколько аргументов, например:

def foo(*bars)
  bars.each { |baz| ... }
end

И пусть вызывающий решит, хочет ли он передать один объект или массив:

foo("XYZ")
ary = ["abc", "def"]
foo(*ary)
1 голос
/ 03 февраля 2015

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

bars = [bar_or_bars].flatten
...