求ruby散列值的和

求ruby散列值的和,ruby,hash,reduce,inject,Ruby,Hash,Reduce,Inject,我试图对ruby哈希中的值求和,但使用inject或reduce都不会返回正确的答案。似乎这些方法正在覆盖存储的当前值,而不是对它们求和 我的哈希如下所示: @test = [ {"total"=>18, "type"=>"buy", "date"=>Thu, 21 Nov 2013, "instrument_code"=>"food"}, {"total"=>92, "type"=>"buy", "date"=>Thu, 14 Nov 2013

我试图对ruby哈希中的值求和,但使用inject或reduce都不会返回正确的答案。似乎这些方法正在覆盖存储的当前值,而不是对它们求和

我的哈希如下所示:

@test = [
  {"total"=>18, "type"=>"buy", "date"=>Thu, 21 Nov 2013, "instrument_code"=>"food"},
  {"total"=>92, "type"=>"buy", "date"=>Thu, 14 Nov 2013, "instrument_code"=>"food"},
  {"total"=>12, "type"=>"buy", "date"=>Wed, 20 Nov 2013, "instrument_code"=>"drink"},
  {"total"=>1, "type"=>"buy", "date"=>Mon, 11 Nov 2013, "instrument_code"=>"food"}
]
{"drink"=>12.0, "food"=>110}
以下是我失败的注入代码:

def additions_per_security
  @test.group_by { |i| i.type }.each do |key, value|
    if key == "buy"
      value.group_by{ |i| i.date }.each do |key, value|
        @sortable_additions[key] = value
      end
      @sorted_additions = @sortable_additions.sort_by { |key,value| key }
      @sorted_additions.shift
      @additions_per_security = Hash[@sorted_additions.map { |key, value| 
       [key, value]
      }]
      @additions_per_security.each do |key, value|
        value.group_by { |i| i.instrument_code }.each do |key, value|
          @additions_security[key] = value.inject(0){ |result, transaction| 
            (result += transaction.total)
          }
        end
      end
    end
  end
  return @additions_security
end
def additions_per_security
  @@test.group_by { |i| i.type }.each do |key, value|
    if key == "buy"
      value.group_by { |i| i.date }.each do |key, value|
        @sortable_additions[key] = value
      end
      @sorted_additions = @sortable_additions.sort_by { |key,value| key }
      @sorted_additions.shift
      @additions_per_security = Hash[@sorted_additions.map { |key, value| 
        [key, value]
      }]
      @additions_per_security.each do |key, value|
        value.group_by { |i| i.instrument_code }.each do |key, value|
          @additions_security[key] = value.map { |p| p.total }.reduce(0,:+)
        end
      end
    end
  end
  return @additions_security
end
下面是我失败的reduce代码:

def additions_per_security
  @test.group_by { |i| i.type }.each do |key, value|
    if key == "buy"
      value.group_by{ |i| i.date }.each do |key, value|
        @sortable_additions[key] = value
      end
      @sorted_additions = @sortable_additions.sort_by { |key,value| key }
      @sorted_additions.shift
      @additions_per_security = Hash[@sorted_additions.map { |key, value| 
       [key, value]
      }]
      @additions_per_security.each do |key, value|
        value.group_by { |i| i.instrument_code }.each do |key, value|
          @additions_security[key] = value.inject(0){ |result, transaction| 
            (result += transaction.total)
          }
        end
      end
    end
  end
  return @additions_security
end
def additions_per_security
  @@test.group_by { |i| i.type }.each do |key, value|
    if key == "buy"
      value.group_by { |i| i.date }.each do |key, value|
        @sortable_additions[key] = value
      end
      @sorted_additions = @sortable_additions.sort_by { |key,value| key }
      @sorted_additions.shift
      @additions_per_security = Hash[@sorted_additions.map { |key, value| 
        [key, value]
      }]
      @additions_per_security.each do |key, value|
        value.group_by { |i| i.instrument_code }.each do |key, value|
          @additions_security[key] = value.map { |p| p.total }.reduce(0,:+)
        end
      end
    end
  end
  return @additions_security
end
我有一个散列,我想对除了第一个日期之外的所有键的总数求和

我目前得到以下信息:

{"drink"=>12.0, "food"=>92}
我的预期结果如下所示:

@test = [
  {"total"=>18, "type"=>"buy", "date"=>Thu, 21 Nov 2013, "instrument_code"=>"food"},
  {"total"=>92, "type"=>"buy", "date"=>Thu, 14 Nov 2013, "instrument_code"=>"food"},
  {"total"=>12, "type"=>"buy", "date"=>Wed, 20 Nov 2013, "instrument_code"=>"drink"},
  {"total"=>1, "type"=>"buy", "date"=>Mon, 11 Nov 2013, "instrument_code"=>"food"}
]
{"drink"=>12.0, "food"=>110}

提前感谢您的建议。

我对您的
inject
代码进行以下观察:

  • 所有变量都不需要是实例变量;局部变量(无
    @
    )就足够了
  • test.group_by{i | i.type}…
    应该是
    test.group_by{i | i[“type”]}…
  • @sortable\u additions[key]=value
    应引发异常,因为尚未创建哈希
  • @sorted_additions.shift
    删除散列的第一个元素并返回该元素,但没有变量接收它(例如,
    h=@sorted_additions.shift
  • @additions_per_security=Hash[@sorted_additions.map{| key,value |[key,value]}]
    显示将@sorted_additions转换为数组,然后返回到相同的哈希
下面是一种实现您想要做的事情的方法

首先,您将传递日期对象。为了解决这个问题,我们将首先为示例中的日期创建这些日期对象:

require 'date'
date1 = Date.parse("Thu, 21 Nov 2013") # => #<Date: 2013-11-21 ((2456618j,0s,0n),+0s,2299161j)>
date2 = Date.parse("Thu, 14 Nov 2013") # => #<Date: 2013-11-14 ((2456611j,0s,0n),+0s,2299161j)>
date3 = Date.parse("Thu, 20 Nov 2013") # => #<Date: 2013-11-20 ((2456617j,0s,0n),+0s,2299161j)>
date4 = Date.parse("Thu, 11 Nov 2013") # => #<Date: 2013-11-11 ((2456608j,0s,0n),+0s,2299161j)>
现在我们计算我们需要什么

test_buy = test.select {|h| h["type"] == "buy"}

earliest = test_buy.min_by {|h| h["date"]}["date"]
  # => #<Date: 2013-11-11 ((2456608j,0s,0n),+0s,2299161j)>

all_but_last = test.reject {|h| h["date"] == earliest}
 # =>  [{"total"=>18, "type"=>"buy", "date"=>date1, "instrument_code"=>"food"},
        {"total"=>92, "type"=>"buy", "date"=>date2, "instrument_code"=>"food"},
        {"total"=>12, "type"=>"buy", "date"=>date3, "instrument_code"=>"drink"}] 
请注意,此处和下方将显示
date1
date2
date3
的值(例如,
date1
将显示
);我在这里使用了变量名作为占位符,以使其更具可读性。此外,所有具有
h[“date”]=最早的
的哈希值
h
都将被拒绝(如果有多个)

我使用了一些临时变量,包括
test\u buy
最早的
除最后一个之外的所有
分组
arr
。您可以通过“链接”来消除其中一些。在这里,我将向您展示如何去除其中一些:

test_buy = test.select {|h| h["type"] == "buy"}
earliest = test_buy.min_by {|h| h["date"]}["date"]
grouped = test_buy.reject {|h| h["date"] == earliest}.group_by \
  {|h| h["instrument_code"]}
Hash[grouped.keys.map {|k| [k, grouped[k].reduce(0) \
  {|t,h| t + h["total"]}]}] # => {"food"=>110, "drink"=>12}
您可能认为这看起来很复杂,但在您获得Ruby的使用经验之后,它将看起来非常自然,并且易于阅读。但是,使用链接的程度是一种样式首选项。

请尝试:

test = [
    {"total"=>18, "type"=>"buy", "date"=>Thu, 21 Nov 2013, "instrument_code"=>"food"},
    {"total"=>92, "type"=>"buy", "date"=>Thu, 14 Nov 2013, "instrument_code"=>"food"},
    {"total"=>12, "type"=>"buy", "date"=>Wed, 20 Nov 2013, "instrument_code"=>"drink"},
    {"total"=>1, "type"=>"buy", "date"=>Mon, 11 Nov 2013, "instrument_code"=>"food"}
]

except_first_date = test.sort_by {|i| i['date'] }
except_first_date.shift

result = except_first_date.inject({}) {|m,i| m[i["instrument_code"]] = m[i["instrument_code"]].to_f + i['total'] ; m }
# => {"food"=>110.0, "drink"=>12.0}

如果您有简单的键/值散列

{1 => 42, 2 => 42}.values.sum
 => 84 

您的testhash是否乱七八糟;在reduce代码中,使用类变量进行testhash。您的方法的复杂性令人不安,没有人能够告诉您为什么
reduce
失败。乔丹,你的第一个问题是
@testhash
不是散列。如果将外部的
{}
更改为
[]
,它将是一个哈希数组;现在它不是一个Ruby对象。另外,
reduce
inject
是同义词。最好通过删除不必要的散列元素来简化和修复testhash。日期,特别是,是不相关的,但可能会导致并发症。拍-你是正确的,我错过了[]@testhash是我正在处理的哈希的简化版本。它只是展示了这个问题的相关关键价值。Cary日期字段在那里,因为我需要对所有值求和,除了第一个日期的值。我已经更新了行与行之间的哈希读数,您对“first date”的引用似乎被解释为“不计算最早值为
date
(此处为@testhash中的最后一个哈希)的哈希值”。您还应该从名称
@testhash
中删除“hash”。请编辑以澄清。是的,这是正确的。我只想要第一个日期之后的任何日期的值,这就是为什么我按“日期”进行分组,排序并删除(.shift)最早的日期这很有效!!非常感谢你。我会继续读你是如何处理的,直到我有更好的理解。我在那里有“type”字段,因为还有“sell”类型,我也需要排除它们。但根据你给我的,我相信我能解决这个问题。非常感谢你的帮助!!!我很高兴你觉得它很有用。您将看到我将“type”字段放回了。
{1=>42,2=>42}.values.sum NoMethodError:undefined方法[42,42]:数组`
{1=>42,2=>30}.values.inject(:+)