Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何对哈希数组进行分组和筛选。红宝石_Ruby - Fatal编程技术网

Ruby 如何对哈希数组进行分组和筛选。红宝石

Ruby 如何对哈希数组进行分组和筛选。红宝石,ruby,Ruby,我有以下数据: @complete_transactions = [{"timestamp"=>"2018-01-18T02:57:34.959Z", "toAddress"=>"Alice", "amount"=>"50"}, {"timestamp"=>"2018-01-18T02:57:35.016Z", "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"12.5"}, {"times

我有以下数据:

@complete_transactions = [{"timestamp"=>"2018-01-18T02:57:34.959Z", "toAddress"=>"Alice", "amount"=>"50"},
 {"timestamp"=>"2018-01-18T02:57:35.016Z", "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"12.5"},
 {"timestamp"=>"2018-01-18T16:53:16.747Z", "toAddress"=>"50", "amount"=>"50"},
 {"timestamp"=>"2018-01-18T16:53:27.572Z", "fromAddress"=>"50", "toAddress"=>"alice", "amount"=>"50"},
 {"timestamp"=>"2018-01-18T16:53:38.853Z", "fromAddress"=>"alice", "toAddress"=>"Alice", "amount"=>"50"},
 {"timestamp"=>"2018-01-23T23:35:03.792Z", "fromAddress"=>"Alice", "toAddress"=>"alice", "amount"=>"10"},
 {"timestamp"=>"2018-01-23T23:35:25.464Z", "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"1"},
 {"timestamp"=>"2018-01-23T23:35:48.835Z", "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"1"},
 {"timestamp"=>"2018-01-23T23:47:46.485Z", "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"1"},
 {"timestamp"=>"2018-01-23T23:48:31.953Z", "fromAddress"=>"Alice", "toAddress"=>"Bobz", "amount"=>"1"},
 {"timestamp"=>"2018-01-24T18:11:04.444Z", "fromAddress"=>"Alice", "toAddress"=>"Bobz", "amount"=>"1"},
 {"timestamp"=>"2018-01-24T18:28:40.680Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"3"},
 {"timestamp"=>"2018-01-24T18:36:53.179Z", "fromAddress"=>"Alice", "toAddress"=>"Sally", "amount"=>"3"},
 {"timestamp"=>"2018-01-24T18:39:14.926Z", "fromAddress"=>"Alice", "toAddress"=>"Sally", "amount"=>"3"},
 {"timestamp"=>"2018-01-24T18:39:40.937Z", "fromAddress"=>"Alice", "toAddress"=>"Sally", "amount"=>"3"},
 {"timestamp"=>"2018-01-24T18:40:11.686Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T18:40:13.720Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T18:41:32.832Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T18:49:10.052Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T18:49:11.729Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T18:50:09.862Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T19:14:46.326Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T20:29:30.973Z", "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"3"},
 {"timestamp"=>"2018-01-24T20:31:37.491Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T20:35:06.693Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T21:29:21.465Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-24T21:29:27.637Z", "fromAddress"=>"Alice", "toAddress"=>"bozb", "amount"=>"2"},
 {"timestamp"=>"2018-01-26T19:04:56.197Z", "fromAddress"=>"Alice", "toAddress"=>"bob", "amount"=>"2"},
 {"timestamp"=>"2018-01-28T19:53:12.502Z", "toAddress"=>"1444", "amount"=>"50"},
 {"timestamp"=>"2018-01-28T19:53:21.318Z", "fromAddress"=>"1444", "toAddress"=>"0297bc77", "amount"=>"1"},
 {"timestamp"=>"2018-01-28T19:53:30.947Z", "fromAddress"=>"1444", "toAddress"=>"0297bc77", "amount"=>"1"},
 {"timestamp"=>"2018-01-28T19:54:11.119Z", "fromAddress"=>"1444", "toAddress"=>"0297bc77", "amount"=>"1"},
 {"timestamp"=>"2018-01-28T21:26:58.551Z", "fromAddress"=>"1444", "toAddress"=>"Alice", "amount"=>"1"},
 {"timestamp"=>"2018-01-28T21:28:13.499Z", "fromAddress"=>"1444", "toAddress"=>"Alice", "amount"=>"2"},
 {"timestamp"=>"2018-01-28T21:31:47.454Z", "fromAddress"=>"1444", "toAddress"=>"something else", "amount"=>"2"},
 {"timestamp"=>"2018-01-28T21:39:16.644Z", "fromAddress"=>"1444", "toAddress"=>"Alice", "amount"=>"3"},
 {"timestamp"=>"2018-01-28T21:39:41.527Z", "fromAddress"=>"1444", "toAddress"=>"Alice", "amount"=>"2"},
我想要的是按
toAddress
字段对数据进行分组,并合计金额

我想要这样的东西(注意时间戳是不相关的):

有什么建议吗

我认为这会产生正确的数据。。。但感觉很恶心:

 complete_transactions.group_by {|trans| trans['toAddress']}.map do |group, transactions|
  transactions.reduce do |h1, h2|
    h1.merge(h2) do |key, old, new|
      if key == 'amount'
        old.to_i + new.to_i
      elsif key == 'fromAddress'
        [old, new].flatten.uniq
      else
        old
      end
    end
  end
end
导致正确的结果,但感觉很恶心。有更好的办法吗

以下是一个小样本数据和预期结果:

 transactions
=> [{"timestamp"=>"2018-01-23T23:48:31.953Z", "fromAddress"=>"Alice", "toAddress"=>"Bobz", "amount"=>"1"}, {"timestamp"=>"2018-01-24T18:11:04.444Z", "fromAddress"=>"Alice", "toAddress"=>"Bobz", "amount"=>"1"}, {"timestamp"=>"2018-01-24T18:11:04.444Z", "fromAddress"=>"Another", "toAddress"=>"Bobz", "amount"=>"1"}]


transactions.reduce do |h1, h2|
irb(main):007:1* h1.merge(h2) do |key, old, new|
irb(main):008:2*   if key == 'amount'
irb(main):009:3>      old.to_i + new.to_i
irb(main):010:3>   elsif key == 'fromAddress'
irb(main):011:3>      [old, new].flatten.uniq
irb(main):012:3>   else
irb(main):013:3*      old
irb(main):014:3>   end
irb(main):015:2>   end
irb(main):016:1> end
=> {"timestamp"=>"2018-01-23T23:48:31.953Z", "fromAddress"=>["Alice", "Another"], "toAddress"=>"Bobz", "amount"=>3}

我相信这就是你在这里需要的

result = @complete_transactions
         .group_by{|hash| hash['toAddress']}
         .map do |key, value|
           {
             'toAddress' => key,
             'amount' => value.sum {|val| val['amount'].to_i},
             'fromAddress' => value.map {|val| val['fromAddress']}.uniq
           }
         end

p result
这适用于2.4.0之后的Ruby版本。对于以前的版本,使用此项计算金额之和

'amount' => value.map {|val| val['amount'].to_i}.inject(:+)
下面的语句按其“toAddress”值对所有哈希进行分组

.group_by{|hash| hash['toAddress']}
followins语句遍历每个结果哈希并创建一个新哈希

.map do |key, value|
在下面的块中,我们通过对每个散列的值进行操作来创建所需的散列

{
  'toAddress' => key,
  'amount' => value.sum {|val| val['amount'].to_i},
  'fromAddress' => value.map {|val| val['fromAddress']}.uniq
}
对于2.4.0之前的Ruby版本,代码变为

{
  'toAddress' => key,
  'amount' => value.map {|val| val['amount'].to_i}.inject(:+),
  'fromAddress' => value.map {|val| val['fromAddress']}.uniq
}

希望这能有所帮助。

我相信这正是您在这里需要的

result = @complete_transactions
         .group_by{|hash| hash['toAddress']}
         .map do |key, value|
           {
             'toAddress' => key,
             'amount' => value.sum {|val| val['amount'].to_i},
             'fromAddress' => value.map {|val| val['fromAddress']}.uniq
           }
         end

p result
这适用于2.4.0之后的Ruby版本。对于以前的版本,使用此项计算金额之和

'amount' => value.map {|val| val['amount'].to_i}.inject(:+)
下面的语句按其“toAddress”值对所有哈希进行分组

.group_by{|hash| hash['toAddress']}
followins语句遍历每个结果哈希并创建一个新哈希

.map do |key, value|
在下面的块中,我们通过对每个散列的值进行操作来创建所需的散列

{
  'toAddress' => key,
  'amount' => value.sum {|val| val['amount'].to_i},
  'fromAddress' => value.map {|val| val['fromAddress']}.uniq
}
对于2.4.0之前的Ruby版本,代码变为

{
  'toAddress' => key,
  'amount' => value.map {|val| val['amount'].to_i}.inject(:+),
  'fromAddress' => value.map {|val| val['fromAddress']}.uniq
}

希望这能有所帮助。

我写了一个方法,提供了您想要的内容,但除此之外,我还包括了一些您没有要求的内容:每个“fromAddress”的贡献占每个“toAddress”的总“金额”。(我误解了这个问题。)\_(ツ)_/”)

代码

def doit(transactions)
  transactions.each_with_object(Hash.new(0)) do |g,h|
    a = [g["fromAddress"], g["toAddress"]]
    h.update(a => h[a] += g["amount"].to_f)
  end.
  group_by { |(_from, to), _amt| to }.
  map { |k,v| { toAddress: k, amount: v.map(&:last).sum.to_s,
                from_address: v.map { |(from, _to), amt| [from, amt.to_s] }.to_h } }
end
示例

def doit(transactions)
  transactions.each_with_object(Hash.new(0)) do |g,h|
    a = [g["fromAddress"], g["toAddress"]]
    h.update(a => h[a] += g["amount"].to_f)
  end.
  group_by { |(_from, to), _amt| to }.
  map { |k,v| { toAddress: k, amount: v.map(&:last).sum.to_s,
                from_address: v.map { |(from, _to), amt| [from, amt.to_s] }.to_h } }
end
让我们将示例简化为更易于管理的内容。我已经消除了
@transactions
的许多元素(散列),并且从剩余的每个散列中,我已经消除了键
“timestamp”
,因为它与问题无关

transactions = [
  { "toAddress"=>"Alice", "amount"=>"50" },
  { "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"12.5" },
  { "toAddress"=>"50", "amount"=>"50" },
  { "fromAddress"=>"50", "toAddress"=>"Alice", "amount"=>"50" },
  { "fromAddress"=>"Alice", "toAddress"=>"Alice", "amount"=>"50" },
  { "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"1" },
  { "fromAddress"=>"1444", "toAddress"=>"0297bc77", "amount"=>"1"},
  { "fromAddress"=>"1444", "toAddress"=>"0297bc77", "amount"=>"1"},
  { "fromAddress"=>"1444", "toAddress"=>"Alice", "amount"=>"1"},
  { "fromAddress"=>"1444", "toAddress"=>"Alice", "amount"=>"2"}
]

doit(transactions)
    #=> [
    #     {:toAddress=>"Alice", :amount=>"153.0",
    #      :from_address=>{nil=>"50.0", "50"=>"50.0", "Alice"=>"50.0", "1444"=>3.0}},
    #     {:toAddress=>"Bob", :amount=>"13.5",
    #      :from_address=>{"Alice"=>"13.5"}},
    #     {:toAddress=>"50", :amount=>"50.0",
    #      :from_address=>{nil=>"50.0"}},
    #     {:toAddress=>"0297bc77", :amount=>"2.0",
    #      :from_address=>{"1444"=>"2.0"}}
    #   ]
如果您不希望返回值包含某些元素,则第一步需要从
事务中删除相应的哈希值(例如,
transactions.reject{| h | |…}。每个_带有_对象…

解释

步骤如下

h = @transactions.each_with_object(Hash.new(0)) do |g,h|
  a = [g["fromAddress"], g["toAddress"]]
  h.update(a => h[a] += g["amount"].to_f)
end
  #=> {[nil, "Alice"]=>50.0, ["Alice", "Bob"]=>13.5, [nil, "50"]=>50.0,
  #    ["50", "Alice"]=>50.0, ["Alice", "Alice"]=>50.0, ["1444", "0297bc77"]=>2.0,
  #    ["1444", "Alice"]=>3.0}
g = h.group_by { |(_from, to), _amt| to }
  #=> { "Alice"=>[[[nil, "Alice"], 50.0], [["50", "Alice"], 50.0],
  #              [["Alice", "Alice"], 50.0], [["1444", "Alice"], 3.0]],
  #     "Bob"=>[[["Alice", "Bob"], 13.5]], "50"=>[[[nil, "50"], 50.0]],
  #     "0297bc77"=>[[["1444", "0297bc77"], 2.0]]}
g.map do |k,v|
  { toAddress: k, amount: v.map(&:last).sum.to_s,
    from_address: v.map { |(from, _to), amt| [from, amt.to_s] }.to_h }
end   
  #=> <return value shown in example>
h=@transactions.each_with_object(Hash.new(0))do|g,h|
a=[g[“fromAddress”],g[“toAddress”]]
h、 更新(a=>h[a]+=g[“金额”].\u f)
结束
#=>{nil,“Alice”]=>50.0,[“Alice”,“Bob”]=>13.5,[nil,“50”]=>50.0,
#[“50”,“Alice”]=>50.0,[“Alice”,“Alice”]=>50.0,[“1444”,“0297bc77”]=>2.0,
#[“1444”,“Alice”]=>3.0}
g=h.群由{124;({U from,to),{U amt}to}
#=>{“爱丽丝”=>[[nil,“爱丽丝”],50.0],[50”,“爱丽丝”],50.0],
#[Alice”,“Alice”],50.0],[1444”,“Alice”],3.0],
#“Bob”=>[[[“Alice”,“Bob”],13.5],“50”=>[[[nil,”50“],50.0],
#“0297bc77”=>2.0]}
g、 图do | k,v|
{toAddress:k,amount:v.map(&:last).sum.to_s,
from|u地址:v.map{|(from,| to),amt |[from,amt.to|s]}to|h}
结束
#=> 

我写了一个方法,提供了你想要的东西,但除此之外,我还包括了一些你没有要求的东西:每个“fromAddress”的贡献占每个“toAddress”的总“金额”。(我误解了这个问题。)\_(ツ)_/”)

代码

def doit(transactions)
  transactions.each_with_object(Hash.new(0)) do |g,h|
    a = [g["fromAddress"], g["toAddress"]]
    h.update(a => h[a] += g["amount"].to_f)
  end.
  group_by { |(_from, to), _amt| to }.
  map { |k,v| { toAddress: k, amount: v.map(&:last).sum.to_s,
                from_address: v.map { |(from, _to), amt| [from, amt.to_s] }.to_h } }
end
示例

def doit(transactions)
  transactions.each_with_object(Hash.new(0)) do |g,h|
    a = [g["fromAddress"], g["toAddress"]]
    h.update(a => h[a] += g["amount"].to_f)
  end.
  group_by { |(_from, to), _amt| to }.
  map { |k,v| { toAddress: k, amount: v.map(&:last).sum.to_s,
                from_address: v.map { |(from, _to), amt| [from, amt.to_s] }.to_h } }
end
让我们将示例简化为更易于管理的内容。我已经消除了
@transactions
的许多元素(散列),并且从剩余的每个散列中,我已经消除了键
“timestamp”
,因为它与问题无关

transactions = [
  { "toAddress"=>"Alice", "amount"=>"50" },
  { "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"12.5" },
  { "toAddress"=>"50", "amount"=>"50" },
  { "fromAddress"=>"50", "toAddress"=>"Alice", "amount"=>"50" },
  { "fromAddress"=>"Alice", "toAddress"=>"Alice", "amount"=>"50" },
  { "fromAddress"=>"Alice", "toAddress"=>"Bob", "amount"=>"1" },
  { "fromAddress"=>"1444", "toAddress"=>"0297bc77", "amount"=>"1"},
  { "fromAddress"=>"1444", "toAddress"=>"0297bc77", "amount"=>"1"},
  { "fromAddress"=>"1444", "toAddress"=>"Alice", "amount"=>"1"},
  { "fromAddress"=>"1444", "toAddress"=>"Alice", "amount"=>"2"}
]

doit(transactions)
    #=> [
    #     {:toAddress=>"Alice", :amount=>"153.0",
    #      :from_address=>{nil=>"50.0", "50"=>"50.0", "Alice"=>"50.0", "1444"=>3.0}},
    #     {:toAddress=>"Bob", :amount=>"13.5",
    #      :from_address=>{"Alice"=>"13.5"}},
    #     {:toAddress=>"50", :amount=>"50.0",
    #      :from_address=>{nil=>"50.0"}},
    #     {:toAddress=>"0297bc77", :amount=>"2.0",
    #      :from_address=>{"1444"=>"2.0"}}
    #   ]
如果您不希望返回值包含某些元素,则第一步需要从
事务中删除相应的哈希值(例如,
transactions.reject{| h | |…}。每个_带有_对象…

解释

步骤如下

h = @transactions.each_with_object(Hash.new(0)) do |g,h|
  a = [g["fromAddress"], g["toAddress"]]
  h.update(a => h[a] += g["amount"].to_f)
end
  #=> {[nil, "Alice"]=>50.0, ["Alice", "Bob"]=>13.5, [nil, "50"]=>50.0,
  #    ["50", "Alice"]=>50.0, ["Alice", "Alice"]=>50.0, ["1444", "0297bc77"]=>2.0,
  #    ["1444", "Alice"]=>3.0}
g = h.group_by { |(_from, to), _amt| to }
  #=> { "Alice"=>[[[nil, "Alice"], 50.0], [["50", "Alice"], 50.0],
  #              [["Alice", "Alice"], 50.0], [["1444", "Alice"], 3.0]],
  #     "Bob"=>[[["Alice", "Bob"], 13.5]], "50"=>[[[nil, "50"], 50.0]],
  #     "0297bc77"=>[[["1444", "0297bc77"], 2.0]]}
g.map do |k,v|
  { toAddress: k, amount: v.map(&:last).sum.to_s,
    from_address: v.map { |(from, _to), amt| [from, amt.to_s] }.to_h }
end   
  #=> <return value shown in example>
h=@transactions.each_with_object(Hash.new(0))do|g,h|
a=[g[“fromAddress”],g[“toAddress”]]
h、 更新(a=>h[a]+=g[“金额”].\u f)
结束
#=>{nil,“Alice”]=>50.0,[“Alice”,“Bob”]=>13.5,[nil,“50”]=>50.0,
#[“50”,“Alice”]=>50.0,[“Alice”,“Alice”]=>50.0,[“1444”,“0297bc77”]=>2.0,
#[“1444”,“Alice”]=>3.0}
g=h.群由{124;({U from,to),{U amt}to}
#=>{“爱丽丝”=>[[nil,“爱丽丝”],50.0],[50”,“爱丽丝”],50.0],
#[Alice”,“Alice”],50.0],[1444”,“Alice”],3.0],
#“Bob”=>[[[“Alice”,“Bob”],13.5],“50”=>[[[nil,”50“],50.0],
#“0297bc77”=>2.0]}
g、 图do | k,v|
{toAddress:k,amount:v.map(&:last).sum.to_s,
from|u地址:v.map{|(from,| to),amt |[from,amt.to|s]}to|h}
结束
#=> 

sum
可以使用块,不需要在那里映射。@StefanPochmann谢谢你的建议。我已经做了更改。@SimpleTime是的,这可能会有帮助。而且,
通过{散列|散列['toAddress']将U分组。大写}
可能更合适。但不确定OP想要什么。获取#的
未定义方法
sum:“@Jwan622这一定是因为您使用的是2.4.0之前的Ruby版本。我也更新了答案以支持这一点。
sum
可以使用块,不需要
映射。@StefanPochmann感谢您的建议ion。我已经做了更改。@SimpleTime是的,这可能会有帮助。而且,
group_by{hash}hash['toAddress']大写]
可能更合适。但不确定OP想要什么。获取#的
未定义方法
sum:“@Jwan622这一定是因为您使用的是Ruby 2.4.0之前的版本。我也更新了答案以支持这一点。您的标题是filter,但我在您的问题中没有看到任何关于筛选的内容?您的标题是filter,但我没有看到我看不到关于filteri的任何信息