str
Если ваша строка JSON:
require 'json'
arr = JSON.parse(str)["groups"]
#=> [{"values"=>"21", "date"=>"2013-02-22"},
# {"values"=>"25", "date"=>"2013-02-22"},
# {"values"=>"20", "date"=>"2013-02-22"},
# {"values"=>"19", "date"=>"2013-02-22"},
# {"values"=>"42", "date"=>"2013-02-10"},
# {"values"=>"30", "date"=>"2013-02-10"},
# {"values"=>"11", "date"=>"2013-02-10"}]
by_date = arr.each_with_object(Hash.new {|h,k| h[k] = []}) { |g,h|
h[g["date"]] << g["values"].to_i }
# => {"2013-02-22"=>[21, 25, 20, 19], "2013-02-10"=>[42, 30, 11]}
dates = by_date.keys
#=> ["2013-02-22", "2013-02-10"]
min_vals, max_vals = *by_date.map { |_,vals| vals.minmax }
#=> [[19, 25], [11, 42]]
min_vals
#=> [19, 25]
max_vals
#=> [11, 42]
Метод Enumerable#each_with_object принимает аргумент, который представляет собой первоначальное значение объекта, который будет построен и возвращаемым методом. Это значение задается второй блочной переменной, h
. Я сделал этот аргумент пустой хэш-значение по умолчанию задается блоком:
{|h,k| h[k] = []}
Что такое «значение по умолчанию»? Все это означает, что если хэш h
не имеет ключа k
, h[k]
возвращает пустой массив. Давайте посмотрим, как это работает здесь.
Первоначально h #=> {}
и each_with_object
устанавливают первый переменный блок, g
равных первое значение arr
: выполняется
g = {"values"=>"21", "date"=>"2013-02-22"}
и блок вычисления:
h[g["date"]] << g["values"].to_i
#=> h["2013-02-22"] << 21
Поскольку h
вовсе нет ключ "2013-02-22"
, h["2013-02-22"]
сначала установлен равным значению по умолчанию, пустой массив:
h["2013-02-22"] = []
затем
h["2013-02-22"] << 21
#=> [21]
h #=> {"2013-02-22"=>[21]}
Когда следующее значение arr
передается к блоку:
g = {"values"=>"25", "date"=>"2013-02-22"}
и h
, как указано выше. Так что теперь вычисление блока:
h[g["date"]] << g["values"].to_i
#=> h["2013-02-22"] << 25
#=> [21, 25]
h #=> {"2013-02-22"=>[21, 25]}
Значение по умолчанию не используется этот раз, как h
имеет ключевое "2013-02-22"
.
одна вещь может потребовать объяснение: «восклицательный знак» *
в:
min_vals, max_vals = *by_date.map { |_,vals| vals.minmax }
Мы видим, что:
by_date.map { |date, vals| vals.minmax }
#=> [[19, 25], [11, 42]]
Если *by_date.map { |date, vals| vals.minmax }
находится на правой стороне равенства, то восклицательный знак причин два элемента из [[19, 25], [11, 42]]
присваиваются переменным с левой стороны равенства, используя параллельное назначение. Странный и замечательный splat operator должен быть в сумке трюков Rubiest.
Поскольку я не использую date
в расчете блока, я обратил на это внимание, заменив date
на локальную переменную _
.
Edit: Для того, чтобы ответить на вопрос, который вы размещены в комментарии, если:
id = [1,1,1,2,2,3,4]
high = [100,100,100,90,90,100,100]
low = [20,20,20,10,10,30,40]
и я правильно понимаю ваш вопрос, вы могли бы сначала вычислить:
indices = id.each_with_index.to_a.uniq(&:first).map(&:last)
#=> [0, 3, 5, 6]
Тогда три массива вы хотите:
id.values_at(*indices)
#=> [1, 2, 3, 4]
high.values_at(*indices)
#=> [100, 90, 100, 100]
low.values_at(*indices)
#=> [20, 10, 30, 40]
Что вы пытаетесь? Функция ['group_by'] (http://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-group_by) здесь очень полезна. – tadman
Добро пожаловать в переполнение стека. Важно дать нам минимальные входные данные, ожидаемый результат и минимальный код, необходимый для воспроизведения проблемы, которую вы видите. Эта последняя часть, минимальный код, необходимый для воспроизведения проблемы, помогает нам НЕ попробовать все возможное, но сосредоточиться на том, как вы атакуете проблему. Как, кажется, вы не пробовали и не хотите, чтобы мы пытались за вас или объяснили, как это сделать, ни то, ни другое из того, как работает SO. –
Когда вы приводите пример в вопросе (как правило, очень хорошо), важно, чтобы входные данные были действительными объектами Ruby. Как вы знаете, объекты JSON являются строками, поэтому вам нужно добавить одинарные кавычки '' {...} ''или использовать'% s [...] 'или heredoc. Кроме того, вы должны назначить все входные значения для переменных, поэтому они могут быть указаны в ответах и комментариях без необходимости их определения. Например, 'str =' '{...}' '. –