Как убрать дублирующую строку в массиве хэшей на Ruby на рельсах - PullRequest
1 голос
/ 08 мая 2019

Я использую Ruby 2.6 в своем приложении.

Я хочу удалить дублирующийся элемент в массиве хэшей. Вот мой вклад

array_of_hashes = [
{"Date"=> "2019-05-6", "ID" => 100, "Rate" => 10, "Count" => 1},
{"Date"=> "2019-05-6", "ID" => 100, "Rate" => nil, "Count" => 0},
{"Date"=> "2019-05-6", "ID" => 101, "Rate" => 25, "Count" => 3},
{"Date"=> "2019-05-6", "ID" => 102, "Rate" => nil, "Count" => 0},
{"Date"=> "2019-05-6", "ID" => 102, "Rate" => 35, "Count" => 0},
{"Date"=> "2019-05-6", "ID" => 103, "Rate" => 20, "Count" => 6}
]

Я создаю пару ключ-значение из хэша для нужд моего приложения.

result = array_of_hashes.map { |row| [[row['ID'], row['Date'], row] }.to_h

Если в хэше есть две записи с одинаковыми значениями «ID» и «Date», я хочу поместить в строку строку, где «Rate»! = 0, где порядок входных записей может измениться. Вот мой фактический и ожидаемый результат.

Фактический результат:

 {[100, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>100, "Rate"=>nil, "Count"=>0},
 [101, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>101, "Rate"=>25, "Count"=>3},
 [102, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>102, "Rate"=>35, "Count"=>0},
 [103, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>103, "Rate"=>20, "Count"=>6}}

Ожидаемый результат:

 {[100, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>100, "Rate"=>10, "Count"=>1}, 
 [101, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>101, "Rate"=>25, "Count"=>3},
 [102, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>102, "Rate"=>35, "Count"=>0},
 [103, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>103, "Rate"=>20, "Count"=>6}}

Как получить ожидаемый выше результат?

Ответы [ 3 ]

3 голосов
/ 08 мая 2019

Вот еще одна группа по опции

array_of_hashes.group_by {|h| h.values_at("ID","Date")}.transform_values do |v|   
  v.find {|r| r["Rate"]}
end

#=> {[100, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>100, "Rate"=>10, "Count"=>1}, 
#    [101, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>101, "Rate"=>25, "Count"=>3}, 
#    [102, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>102, "Rate"=>35, "Count"=>0}, 
#    [103, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>103, "Rate"=>20, "Count"=>6}}

, сгруппированная по идентификатору и дате, затем преобразуйте значения Hash в первое Hash, где «Rate» не равно nil.

Если допустимы несколько значений, тогда find.

можно заменить find_all или select. Если вы хотите сохранить исходную структуру, просто добавьте values в конец.

2 голосов
/ 08 мая 2019

Мы можем построить желаемый хеш, сделав один проход через array_of_hashes.

array_of_hashes.each_with_object({}) do |g,h|
  k = [g['ID'], g['Date']]
  h.update(k=>g) unless h.key?(k) && h[k]['Rate'] != nil
end
  #=> {[100, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>100, "Rate"=>10, "Count"=>1},
  #    [101, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>101, "Rate"=>25, "Count"=>3},
  #    [102, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>102, "Rate"=>35, "Count"=>0},
  #    [103, "2019-05-6"]=>{"Date"=>"2019-05-6", "ID"=>103, "Rate"=>20, "Count"=>6}}

Это предполагает, что если два элемента array_of_hashes совпадают со значениями 'ID' и 'Date'и ни один из них не имеет значения nil для 'Rate', первый из двух хешей сохраняется.Если последнее из двух должно быть сохранено, измените вторую строку метода на:

h.update(k=>g) unless h.key?(k) && g['Rate'].nil?
1 голос
/ 08 мая 2019

Используйте group_by и отфильтруйте нулевые ставки по значениям.

array_of_hashes
  .group_by { |h| [h["ID"], h["Date"]] }
  .map { |key, values| [key, values.reject { |row| row["Rate"].nil? }.last] }
  .to_h
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...