Добавить элемент в массив в Ruby, даже если переменная не существует

У меня есть следующее:

foo ||= []
foo << "bar"

И я уверен, что это можно сделать в одну строку, я просто не могу найти, как это сделать.

Важно то, что foo может существовать, а может и не существовать. Если он существует, это всегда массив, если он не существует, он должен стать массивом и получить присоединенную к нему переменную.


person berkes    schedule 09.03.2011    source источник


Ответы (3)


Как это:

(foo ||= []) << "bar"

Бит в скобках возвращает foo, если он уже существует, или создает его, если нет, а затем к нему добавляется <<.

person glenn mcdonald    schedule 09.03.2011
comment
Это лучше, чем мой ответ. - person dbyrne; 09.03.2011

Если вы хотите добавить "bar" только тогда, когда foo еще не определено:

foo ||= ["bar"]

если вы хотите добавить "bar" независимо от того, существует ли уже foo:

(defined? foo) ? foo << "bar" : foo = ["bar"]

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

person dbyrne    schedule 09.03.2011
comment
Я сам только начинаю изучать рубин, поэтому, возможно, я что-то упускаю, но это, похоже, не работает для в любом случае. В случае, если foo не существует, ему просто присваивается значение nil, а в случае, если он существует, к нему ничего не добавляется. - person Benjamin Lindley; 09.03.2011
comment
@Benjamin Какую версию Ruby вы используете? Я использую JRuby 1.5.0. - person dbyrne; 09.03.2011
comment
А... мне нужны скобки. Ответ исправлен. - person dbyrne; 09.03.2011

Какой код вы пишете, когда не уверены, существует ли локальная переменная?

Если это что-то вроде

def procedural_method(array)
  result ||= []
  array.each do |array_item|
    result << bar(array_item)
  end
  result
end

тогда вы можете попробовать более функциональный подход к программированию

def functional_programming_method(array)
  array.map do |array_item|
    bar(array_item)
  end
end
person Andrew Grimm    schedule 09.03.2011
comment
Дело в том, что действие Rails FooController#create должно добавлять элементы в глобальный хэш сеанса: session[:comments] << id. Не только FooController добавляет к этому хэшу, но потенциально и другие. Теперь, когда я пишу это, я понимаю, что геттер и сеттер в помощнике, вероятно, намного лучше. - person berkes; 10.03.2011