2014-09-15 3 views
0

У меня есть массив хешей, представляющих дни записанной информации о погоде.Почему мой метод инъекции не работает? Кажется, что правильно построено

data = [ 
    {"temp": "22", "rain": "0.5"}, 
    {"temp": "30", "rain": "1.5"}, 
    {"temp": "40", "rain": "2.8"} 
} 

Я хочу получить общее количество осадков за все дни. Итак, я пишу

puts data.inject{|rain, day| rain + day['rain'].to_f} 

Но я вернусь ошибку undefined method [] for nil.

Что я сделал не так?

+2

Литерал, который вы опубликовали ('data') не является синтаксически действительным, исправьте его, чтобы люди могли его скопировать и вставить, чтобы протестировать ваш код. – toro2k

+0

JSON не является собственной структурой данных Ruby. –

+1

С вашим последним * edit *, вы должны получить ** другую ** ошибку. Обновите с фактической ошибкой. –

ответ

2

Использовать 0 в качестве начального аргумента.

puts data.inject(0) { |rain, day| rain + day['rain'].to_f } 

Теперь rain будет инициализирован с 0 в первой итерации и day к Hash объектов data массива. Теперь с секунд итераций на каждом шаге, каждый раз rain будет удерживать результат rain + day['rain'].to_f и day до следующего Hash. Прочтите официальную документацию #inject.

Если вы укажете блок, то для каждого элемента в перечислении блок передается значение аккумулятора (памятка) и элемент. Если вы укажете вместо этого символ, то каждый элемент в коллекции будет передан именованному методу memo. В любом случае результат становится новым значением для памятки. В конце итерации конечное значение memo является возвращаемым значением для метода.

Если вы явно не указали начальное значение для memo, тогда первый элемент коллекции используется как начальное значение memo.

1

inject с блоком, но без первоначальной памятки аргумента инициализирует памятку (rain в вашем случае) nil. Ниль не может быть добавлен к (nil + 2 #!bang). Кроме того, вы не закрываете массив данных правильно (с ]). Со следующим кодом он должен работать.

data = [ 
    {"temp" => "22", "rain" => "0.5"}, 
    {"temp" => "30", "rain" => "1.5"}, 
    {"temp" => "40", "rain" => "2.8"} 
] 
puts data.inject(0){|rain, day| rain + day['rain'].to_f} # => 4.8 
0

Прежде всего, вы должны быть уверены, что ваши данные существуют. В этом случае

  1. Фикс фигурная скобка
  2. Это лучше сделать ключи Hash, как символов, но не строки. Для строкового ключа вы должны использовать синтаксис 'key' => 'value'.

Таким образом, вы должны изменить это:

data = [ 
    {"temp": "22", "rain": "0.5"}, 
    {"temp": "30", "rain": "1.5"}, 
    {"temp": "40", "rain": "2.8"} 
] 

к этому. Вот выход IRB:

?> data = [ 
?>  {temp: "22", rain: "0.5"}, 
?>  {temp: "30", rain: "1.5"}, 
?>  {temp: "40", rain: "2.8"} 
>> ] 
=> [{:temp=>"22", :rain=>"0.5"}, {:temp=>"30", :rain=>"1.5"}, {:temp=>"40", :rain=>"2.8"}] 

Вы получили Array из Hashes.

Следующая является map функция:

puts data.map {|rain, day| rain + day['rain'].to_f} 

Это неправильно. Вы должны обратиться каждый элемент массива один за другим:

puts data.map {|i| puts i[:temp] + ' ' + i[:rain] } 

Вот i переменная, которая относится к каждый элемент массива. Каждый элемент - Hash с :temp и :rain ключами.

Теперь вы можете суммировать с inject(0):

puts data.inject(0){|rain, day| rain + day[:rain].to_f} 

Попробуйте! Удачи!

Смежные вопросы