从数组中匹配元素

app*_*ver 0 ruby set matching

我有如下数据结构.

[{"league"=>:nba, "period"=>"h1","edge"=>-5.0, "home_team"=>"Cavaliers"},   
{"league"=>:nba, "period"=>"h1", "edge"=>-6.0, "home_team"=>"Pistons"}, 
{"league"=>:nba, "period"=>"h1", "edge"=>-6.0, "home_team"=>"Bucks"},   
{"league"=>:ncaab, "period"=>"h1", "edge"=>-7.0, "home_team"=>"Wisconsin"},   
{"league"=>:ncaab, "period"=>"h1", "edge"=>-7.0, "home_team"=>"Wisconsin"}]
Run Code Online (Sandbox Code Playgroud)

我需要为数组中的每个元素分配一个新的键/值对,key = "id",value = x,其中x是一个整数.本x应是每一个元素,它同样"period""home_team"值是相同的,否则什么x是无所谓.所以上面应该会产生这样的结果:

[{"league"=>:nba, "period"=>"h1","edge"=>-5.0, "home_team"=>"Cavaliers", "id"=>1},   
{"league"=>:nba, "period"=>"h1", "edge"=>-6.0, "home_team"=>"Pistons", "id"=>2},    
{"league"=>:nba, "period"=>"h1", "edge"=>-6.0, "home_team"=>"Bucks", "id"=>3},  
{"league"=>:ncaab, "period"=>"h1", "edge"=>-7.0, "home_team"=>"Wisconsin", "id"=>4},   
{"league"=>:ncaab, "period"=>"h1", "edge"=>-7.0, "home_team"=>"Wisconsin", "id"=>4}]
Run Code Online (Sandbox Code Playgroud)

Car*_*and 5

你可以使用Enumerable#group_by:

def id_em(items)
  items.group_by { |h,i| [h["period"],h["home_team"]] }
       .map.with_index { |(_,v),i| v.map { |h| h.merge({id: i})} }
       .flatten
end
Run Code Online (Sandbox Code Playgroud)

例子

items = [{"league"=>:nba,   "period"=>"h1", "home_team"=>"Cavaliers"},
         {"league"=>:nba,   "period"=>"h1", "home_team"=>"Pistons"},
         {"league"=>:nba,   "period"=>"h1", "home_team"=>"Bucks"},
         {"league"=>:ncaab, "period"=>"h1", "home_team"=>"Wisconsin"},
         {"league"=>:ncaab, "period"=>"h1", "home_team"=>"Wisconsin"}]

id_em(items)
  #=> [{"league"=>:nba,   "period"=>"h1", "home_team"=>"Cavaliers", :id=>0},
  #    {"league"=>:nba,   "period"=>"h1", "home_team"=>"Pistons",   :id=>1},
  #    {"league"=>:nba,   "period"=>"h1", "home_team"=>"Bucks",     :id=>2},
  #    {"league"=>:ncaab, "period"=>"h1", "home_team"=>"Wisconsin", :id=>3},
  #    {"league"=>:ncaab, "period"=>"h1", "home_team"=>"Wisconsin", :id=>3}]

items = [{"league"=>:nba1, "period"=>"h1", "home_team"=>"Cavaliers"},
         {"league"=>:nba2, "period"=>"h2", "home_team"=>"Pistons"},
         {"league"=>:nba3, "period"=>"h2", "home_team"=>"Pistons"},
         {"league"=>:nba4, "period"=>"h1", "home_team"=>"Cavaliers"}]

p id_em(items)
  #=> [{"league"=>:nba1, "period"=>"h1", "home_team"=>"Cavaliers", :id=>0},
  #    {"league"=>:nba4, "period"=>"h1", "home_team"=>"Cavaliers", :id=>0},
  #    {"league"=>:nba2, "period"=>"h2", "home_team"=>"Pistons",   :id=>1},
  #    {"league"=>:nba3, "period"=>"h2", "home_team"=>"Pistons",   :id=>1}]
Run Code Online (Sandbox Code Playgroud)

说明

对于items上面的第二个示例数组

a = items.group_by { |h,i| [h["period"],h["home_team"]] }
  #=> {["h1", "Cavaliers"] =>
  #      [{"league"=>:nba1, "period"=>"h1", "home_team"=>"Cavaliers"},
  #       {"league"=>:nba4, "period"=>"h1", "home_team"=>"Cavaliers"}],
  #    ["h2", "Pistons"]   =>
  #      [{"league"=>:nba2, "period"=>"h2", "home_team"=>"Pistons"},
  #       {"league"=>:nba3, "period"=>"h2", "home_team"=>"Pistons"}]}

b = a.map.with_index { |(_,v),i| v.map { |h| h.merge({id: i})} }
  #=> [[{"league"=>:nba1, "period"=>"h1", "home_team"=>"Cavaliers", :id=>0},
  #     {"league"=>:nba4, "period"=>"h1", "home_team"=>"Cavaliers", :id=>0}],
  #    [{"league"=>:nba2, "period"=>"h2", "home_team"=>"Pistons",   :id=>1},
  #     {"league"=>:nba3, "period"=>"h2", "home_team"=>"Pistons",   :id=>1}]]

b.flatten
  #=> [{"league"=>:nba1, "period"=>"h1", "home_team"=>"Cavaliers", :id=>0},
  #    {"league"=>:nba4, "period"=>"h1", "home_team"=>"Cavaliers", :id=>0},
  #    {"league"=>:nba2, "period"=>"h2", "home_team"=>"Pistons",   :id=>1},
  #    {"league"=>:nba3, "period"=>"h2", "home_team"=>"Pistons",   :id=>1}]
Run Code Online (Sandbox Code Playgroud)

在计算中b,传递给块的第一个数组被赋予给定的块变量

|(k,v),i|
Run Code Online (Sandbox Code Playgroud)

如下:

k = ["h1", "Cavaliers"]
v = [{"league"=>:nba1, "period"=>"h1", "home_team"=>"Cavaliers"},
     {"league"=>:nba4, "period"=>"h1", "home_team"=>"Cavaliers"}], 
i = 0
Run Code Online (Sandbox Code Playgroud)

我们不会使用k,所以将它替换为块变量_.

map将第一个元素转换v为:

{"league"=>:nba1, "period"=>"h1", "home_team"=>"Cavaliers"}.merge({id: 0})
  #=> {"league"=>:nba1, "period"=>"h1", "home_team"=>"Cavaliers", :id=>0}
Run Code Online (Sandbox Code Playgroud)

和第二个元素:

{"league"=>:nba4, "period"=>"h1", "home_team"=>"Cavaliers"}.merge({id: 0})
  #=> {"league"=>:nba4, "period"=>"h1", "home_team"=>"Cavaliers", :id=>0}
Run Code Online (Sandbox Code Playgroud)