2 votes

Ruby : itération et imbrication de hachages sur condition

J'ai deux tableaux de hachages comme ceci :

h1=[{id:1, item:1, from: DateTime.new(2017,9,4,6,0,0,'+0300'), to: DateTime.new(2017,9,4,17,59,59,'+0300'), value:10},
    {id:1, item:2, from: DateTime.new(2017,9,4,18,0,0,'+0300'), to: DateTime.new(2017,9,4,23,59,59,'+0300'), value:10}]

h2=[{id:1, item:1, date: DateTime.new(2017,9,4,6,10,0,'+0300'), value:5},
    {id:2, item:1, date: DateTime.new(2017,9,4,7,20,0,'+0300'), value:7},
    {id:3, item:1, date: DateTime.new(2017,9,4,8,05,0,'+0300'), value:10},
    {id:4, item:1, date: DateTime.new(2017,9,4,18,19,10,'+0300'), value:1},
    {id:5, item:2, date: DateTime.new(2017,9,4,19,20,0,'+0300'), value:2},
    {id:6, item:2, date: DateTime.new(2017,9,4,22,22,0,'+0300'), value:5},
    {id:7, item:2, date: DateTime.new(2017,9,5,23,0,0,'+0300'), value:1}]

J'ai besoin de me nicher sous chaque h1 tout hachage de h2 qui correspondent aux critères :

  1. item (par exemple, item:1 dans les deux hachages)
  2. date de h2 est en from - to gamme en h1

Jusqu'à présent, je peux simplement emboîter tous les hashs sous h1 avec celui-ci :

my_hash = h1.each do 
  |mh| mh[:inventory]=h2
end

Je crois que l'on pourrait faire une correspondance de critères avec ceci :

h2.find{ |i| i[:item] == h1[:item] && i[:date].between?(h2[:from], h2[:to]) }

Comment dois-je faire pour que ça marche, s'il vous plaît ? Merci.

Mise à jour 2

J'essaie de trouver pour chaque h1 jumelé h2 haché avec celui-ci :

my_hash = h1.each do |hsh| 
  h2.each do |hsh2| 
    hash=hsh2.find{|h| h[:item] == hsh[:item] && h[:date].between?(hsh[:from],hsh[:to])} if hash
    hsh[:inventory] = hash
  end 
end

mais je reçois une erreur ArgumentError: wrong number of arguments (given 1, expected 0) from (pry):12:in "hash" . Qu'est-ce que je fais de mal ici, s'il vous plaît ?

Mise à jour 3 Si possible, la sortie idéale serait quelque chose comme ceci :

=> [:order=>{:id=>1,
  :item=>1,
  :from=>Mon, 04 Sep 2017 06:00:00 +0300,
  :to=>Mon, 04 Sep 2017 17:59:59 +0300,
  :value=>10,
  :inventory=>
   {:id=>1, :item=>1, :date=>Mon, 04 Sep 2017 06:10:00 +0300, :value=>5},
   {:id=>2, :item=>1, :date=>Mon, 04 Sep 2017 07:20:00 +0300, :value=>7},
   {:id=>3, :item=>1, :date=>Mon, 04 Sep 2017 08:05:00 +0300, :value=>10}
  :order=>{:id=>1,
  :item=>2,
  :from=>Mon, 04 Sep 2017 18:00:00 +0300,
  :to=>Mon, 04 Sep 2017 23:59:59 +0300,
  :value=>10,
  :inventory=>
   {:id=>4, :item=>2, :date=>Mon, 04 Sep 2017 18:19:10 +0300, :value=>1},
   {:id=>5, :item=>2, :date=>Mon, 04 Sep 2017 19:20:00 +0300, :value=>2},
   {:id=>6, :item=>2, :date=>Mon, 04 Sep 2017 22:22:00 +0300, :value=>5},
   {:id=>7, :item=>2, :date=>Mon, 04 Sep 2017 23:00:00 +0300, :value=>1}}]

Pour chaque h1 Je voudrais donner une nouvelle clé order et ensuite imbriquer les éléments appropriés h2 Les hachages sous inventory clé.

2voto

Schylar Points 629

Cela fonctionne sur ruby 2.4.2p198 (2017-09-14 révision 59899) [x64-mingw32].

h1.each do |hsh1|
    hsh1[:inventory] =
        h2.find do |hsh2|
            hsh2[:item] == hsh1[:item] &&
            hsh2[:date].between?(hsh1[:from],hsh1[:to])
        end || Hash.new
end

Vous pouvez jouer avec la valeur par défaut de hsh1[:inventory] en remplaçant Hash.new avec la valeur par défaut souhaitée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X