2014-09-16 12 views
0

у меня есть хэш, который выглядит следующим образомmax_by возвращение неверного значения

@hash = { 1=>[], 2=>[], 3=>[], 4=>[],5=>[], 6=>[], 7=>[ 
[{"value"=>1.58, "title"=>"sun", "quantity" => 2}], 
[{"value"=>1.99, "title"=>"sophia", "quantity" => 5}], 
[{"value"=>6.30, "title"=>"roam", "quantity" => 15}], 
[{"value"=>3.981, "title"=>"jia", "quantity" => "4"}]], 8 => [], 9 => [], 10 => [] } 

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

из пут должны выглядеть следующим образом

@hash = { 1=>nil, 2=>nil, 3=> nil, 4=>nil,5=>nil, 6=>nil, 7=>[ 
[{"value"=>6.30, "title"=>"roam", "quantity" => 15}], 8 => nil, 9 => nil, 10 => nil } 

Я надеюсь, что ожидаемый выход ясно

Так что я пытаюсь получить максимум от следующего кода

for t in 0..10 
    if [email protected][t].nil?                  
     @hash[t] = @hash[t].max_by{|i| i[0]['value'].to_i} 
     puts "----------" 
     puts @hash.to_s 
    end 
    end 

, но я получаю только первое значение формы хэширования и нуль для других индексов вместо придания максимального значения для данного индекса. В путах в этом цикле дает мне это что неправильно

[{"title":"sun","value":1.58, "quantity => 2"}], null, null, null, null.. 

не знает, что это неправильно

+0

вы хотите следить за ид массива? или просто хеш-значение? –

+0

только хеш-значение ... –

ответ

0

здесь:

@hash = { 1=>[], 2=>[], 3=>[], 4=>[],5=>[], 6=>[], 7=>[ 
[{"value"=>1.58, "title"=>"sun", "quantity" => 2}], 
[{"value"=>1.99, "title"=>"sophia", "quantity" => 5}], 
[{"value"=>6.30, "title"=>"roam", "quantity" => 15}], 
[{"value"=>3.981, "title"=>"jia", "quantity" => "4"}]], 8 => [], 9 => [], 10 => [] } 

@hash.each do |k, v| 
    if v.empty? 
    @hash[k] = nil 
    else 
    @hash[k] = [v.flatten.sort{ |v1, v2| v2['value'] <=> v1['value'] }.first] 
    end 
end 

puts @hash.inspect 
#=> {1=>nil, 2=>nil, 3=>nil, 4=>nil, 5=>nil, 6=>nil, 7=>[{"value"=>6.3, "title"=>"roam", "quantity"=>15}], 8=>nil, 9=>nil, 10=>nil} 
+0

aha, теперь он работал для этого, но один вопрос. Если мне нужно снова найти максимальное значение среди всего индекса, то это правильно, как это .... max_value = @ hash.values.select {| v | v} .map {| v | v.first ['value']} .max –

+0

Yup, моя первоначальная итерация заключалась в том, чтобы найти максимальное значение, а затем сделать выбор по хэш-значениям. – Surya

+0

Вы можете: '@ hash.values.flatten.map {| v1 | v1 ['value']} .max' – Surya

0

Я думаю, что это делает то, что вы хотите:

@hash.map do |key, things| 
    [ 
    key, 
    things.max_by { |thing| thing.first["value"].to_i } 
    ] 
end.to_h 

Простите бесполезные имена переменных, я не совсем уверен, что представляет ваша структура данных Я не могу выбрать лучшие имена.

Отметьте, что это не редактирует @hash, но возвращает новый хеш.

+0

Это опрятный приятель. Обратите внимание, что '.to_h' будет работать только для Ruby 2.1.x или выше. Хороший ответ, хотя. – Surya

+0

Ах, по какой-то причине я думал, что 'Array # to_h' также был включен в activesupport. Другой вариант - обернуть всю вещь в 'Hash [...]' или преобразовать возвращаемое значение 'map' в хеш, например: hash_array = @ hash.map ...; @hash = Hash [hash_array] '. – henrikhodne

+0

или вы можете 'map.with_object ({})', который, по моему мнению, выглядит более чистым, чем упаковка с помощью 'Hash'. – engineersmnky

0

Использование #max_by по запросу (Не знаю, почему вы, как и многие другие ответы, хотят уничтожить исходный хэш. Все ниже методы не являются деструктивными и возвратит запрошенные результаты.)

@hash.map.with_object({}) do |(k,v),obj| 
    obj[k] = v.empty? ? nil : [v.flatten.max_by{ |h| h["value"]}] 
end 
#=>{1=>nil, 2=>nil, 3=>nil, 4=>nil, 5=>nil, 6=>nil, 7=>[{"value"=>6.3, "title"=>"roam", "quantity"=>15}], 8=>nil, 9=>nil, 10=>nil} 

Это может быть более чистым, если вы не хотите, чтобы 7-й элемент представлял собой массив из 1, который в любом случае не имеет для меня никакого смысла, например

@hash.map.with_object({}) do |(k,v),obj| 
    obj[k] = v.flatten.max_by{ |h| h["value"]} 
end 
#=> {1=>nil, 2=>nil, 3=>nil, 4=>nil, 5=>nil, 6=>nil, 7=>{"value"=>6.3, "title"=>"roam", "quantity"=>15}, 8=>nil, 9=>nil, 10=>nil} 

Почему вам нужен массив одного элемента, когда все это будет делать, это добавить сложность? Если вы не добавите этот элемент позже?

Или другой способ

@hash.map.with_object({}) do |(k,v),obj| 
    obj[k] = v.max_by{|a| a.is_a?(Array) ? a[0]['value'] : a.to_f} 
end 
2
@hash = { 1=>[], 2=>[], 3=>[], 4=>[],5=>[], 6=>[], 7=>[ 
[{"value"=>1.58, "title"=>"sun", "quantity" => 2}], 
[{"value"=>1.99, "title"=>"sophia", "quantity" => 5}], 
[{"value"=>6.30, "title"=>"roam", "quantity" => 15}], 
[{"value"=>3.981, "title"=>"jia", "quantity" => "4"}]], 8 => [], 9 => [], 10 => [] } 

@hash.each do |key, values| 
    if values.empty? 
    @hash[key] = nil 
    else 
    @hash[key] = [values.flatten.max_by{|h| h["value"]}] 
    end 
end 

p @hash 
+0

Почему вы хотите уничтожить объект '@ hash' для выполнения такой задачи? – engineersmnky

+0

Я предполагаю, что требования таковы, что исходный хэш никогда не будет использоваться – kapiltekwani

0

Вот код, который даст нужный результат:

output_hash = {} 

@hash.keys.each do |k| 
    output_hash[k] = @hash[k].flatten.max{ |a, b| a["value"] <=> b["value"] } 
end 

puts output_hash 
0

Это легко может быть сделано с помощью одного лайнера, вы можете заменить sort_by с max_by если вам просто нужно одно значение

Сортировка значений descendin г

@hash.values.reject(&:empty?).flatten.sort_by{|x| x['value']} 

Максимальное значение хэш

@hash.values.reject(&:empty?).flatten.max_by{|x| x['value']} 
Смежные вопросы