当前位置: 首页 > 知识库问答 >
问题:

Ruby on Rails - Ruby,如何用相同的键将两个散列值相加,而不覆盖这些值?

暴招
2023-03-14

首先,感谢您帮助我解决SQL问题。

现在我正在为另一件事而苦苦挣扎,这让我想我是否应该放弃做一个程序员。

无论如何,我的问题是:我有一个哈希数组(在该哈希数组中还有另一个),如下所示:

[
 {"A1"=>{:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}}, 
 {"A1"=>{:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}},
 {"A3"=>{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}},
 ...
]

我试图实现的是,如果有两个具有相同键的值,即“A1”将这些值添加到一个完整的哈希中,而不会覆盖旧值并将月份作为所需的键输出:

[
 {"A1"=> { 1 => { :balance=> "0.0000", :price=>"9.0000"} },
         { 7 => { :balance => "34030.0000", :price => "34030.0000" } }},
  and so on... 
]

这是可能的吗?

共有3个答案

通骁
2023-03-14

可以说,期望的返回值是一个散列会更有用:

h = {"A1"=>{1=>{:balance=>    "0.0000", :price=>    "9.0000"},
            7=>{:balance=>"34030.0000", :price=>"34030.0000"}},
     "A3"=>{4=>{:balance=>"34030.0000", :price=>"34030.0000"}}}

这样你就可以写出,例如:

require 'bigdecimal'

BigDecimal(h['A1'][7][:price]) 
  #=> 0.3403e5

请参见BigDecimal。BigDecimal通常用于财务计算,因为它避免了舍入错误。

通过将:month的值更改为arr中的整数,可以获得此结果:

arr = [
  {"A1"=>{:month=>1, :balance=>    "0.0000", :price=>    "9.0000"}}, 
  {"A1"=>{:month=>7, :balance=>"34030.0000", :price=>"34030.0000"}},
  {"A3"=>{:month=>4, :balance=>"34030.0000", :price=>"34030.0000"}}
]

并且通过计算:

h = arr.each_with_object({}) do |g,h|
  k,v = g.flatten
  (h[k] ||= {}).update(v[:month]=>v.reject { |k,_| k == :month })
end

请参见Hash#flatten、Hash#update(又名merge!)和Hash#reject。

也可以这样写:

h = arr.each_with_object(Hash.new { |h,k| h[k] = {} }) do |g,h|
  k,v = g.flatten
  h[k].update(v[:month]=>v.reject { |k,_| k == :month })
end

参见采用块的Hash::new的形式。

黄隐水
2023-03-14

@Sebastian的回答很优秀。为了多样化,让我们也考虑一种迭代方法。不确定这样更有效率还是更容易理解,但是多角度理解总是好的。

设置您给我们的输入数据:

arr = [
 {"A1"=>{:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}}, 
 {"A1"=>{:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}},
 {"A3"=>{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}}]

我们为结果创建一个新的空散列。

new_hash = {}

现在迭代原始数据。我们将对数据的形式做一些假设。

# We know each thing is going to be a hash.
arr.each do |hsh|
    # Set up some convenient variables for keys and 
    # values we'll need later.
    key = hsh.keys.first
    value = hsh.values.first
    month = value[:month]
    
    # If the output hash doesn't yet have the key,
    # give it the key and assign an empty hash to it.
    new_hash[key] ||= {}
    # Assign the value to the hash, keyed to the current month.
    new_hash[key][month] = value
    # ... and get rid of the month key that's now redundant.
    new_hash[key][month].delete(:month)
end

结果是:

{"A1"=>{1.0=>{:balance=>"0.0000", :price=>"9.0000"}, 
        7.0=>{:balance=>"34030.0000", :price=>"34030.0000"}}, 
 "A3"=>{4.0=>{:balance=>"34030.0000", :price=>"34030.0000"}}}
严宇
2023-03-14

由于您现有数据的当前格式,您将需要更多的转换。其中大部分都是基于在通过唯一的键对数组中的散列进行分组之后,对结果散列的值进行转换:

data
  .group_by { |hash| hash.keys.first }                                     # (1)
  .transform_values { |value| value.flat_map(&:values) }                   # (2)
  .transform_values { |values| values.index_by { |value| value[:month] } } # (3)

第一个转换是按其唯一的哈希键对当前对象进行分组,其中包含一个哈希数组,因此是 keys.first,结果是:

{
  "A1"=>[
    {"A1"=>{:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}}, 
    {"A1"=>{:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}}
  ],
  "A3"=>[{"A3"=>{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}}]
}

第二种方法是仅从每个哈希中提取值,在生成的哈希中,使用哈希数组:

{
  "A1"=>[
    {:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}, 
    {:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}
  ],
  "A3"=>[{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}]
}

然后,它只需要将哈希数组转换为简单的哈希,其键为month的值:

{
  "A1"=>{
    1.0=>{:month=>1.0, :balance=>"0.0000", :price=>"9.0000"}, 
    7.0=>{:month=>7.0, :balance=>"34030.0000", :price=>"34030.0000"}
  },
  "A3"=>{4.0=>{:month=>4.0, :balance=>"34030.0000", :price=>"34030.0000"}}
}
 类似资料:
  • 我有两个哈希要合并。它们看起来像这样: 第二个散列看起来像: 我想合并这两个散列数组,结果如下所示: 有没有一种简单的方法来合并这两个哈希,或者我必须逐个遍历哈希并在另一个哈希中找到该键?

  • 我想找到一种有效的方法将两个哈希合并在一起,并且生成的哈希必须包含所有原始数据和基于以下标准的新键/值对。两个哈希之间没有共同的键,但是一个哈希中的键与相邻哈希中的一个键的值匹配。 还要注意,第二个散列实际上是一个散列数组。 我正在处理一个相对较大的数据集,因此正在寻找一个有效的解决方案,但希望同时保持代码的可读性,因为它可能最终会投入生产。 以下是我的数据结构: 以下是我需要完成的任务: 我需要

  • 所以我有以下 2 个数组,键为 2016 和 现在,在数组合并之后,我应该得到一个具有2个数据键的数组,和,但是我得到了一个具有3个键的数组。 为什么会这样?正常吗? 信息: PHP 5.6.30 (cli) (构建时间: Feb 7 2017 16:18:37) 版权所有 (c) 1997-2016 PHP 组 Zend Engine v2.6.0, 版权所有 (c) 1998-2016 Zen

  • 我正在做一个骰子游戏,我想在初始掷骰时显示两个骰子相加的值。 我如何实现这一目标?现在它只显示两个数字在一起,我不确定应该将其设置为什么,以便显示两个骰子的附加掷骰值。我有接线员: 让rollpt=(dice1 dice2);document.getElementById("点"). innerHTML="第一个滚动点:"rollpt; 例如,dice1掷3,dice2掷6,我希望javascri

  • 为什么它不打印“processTextPosition:ContainsKey”?

  • 问题内容: 例如,在mysql中更新表时: 表 如果我运行查询 MYSQL会再次写入相同的值还是因为内容相同而忽略它? 这是我提出的问答问题,正如Stack Overflow鼓励的那样,我认为这对于将来有相同问题的其他程序员将是有用的。 问题答案: 正如MYSQL手册中UPDATE语句所暗示的那样, 如果将列设置为其当前值,MySQL会注意到这一点,并且不会对其进行更新。 因此,如果运行此查询,M