【问题标题】:How to map ruby hashes correctly based on key provided如何根据提供的密钥正确映射 ruby​​ 哈希
【发布时间】:2020-06-11 20:29:17
【问题描述】:

我的数据是这样的:

h = { themes_data: {
    Marketing: [
        {
            id: 68,
            projectno: "15",
        }
    ],
    Produktentwicklung: [
        {
            id: 68,
            projectno: "15",
        },
        {
            id: 4,
            projectno: "3",
        }
    ],
    Marketing_summary: [
        {
            ges: {
                result: "47.6"
            },
            theme: "Marketing"
        }
    ],
    Produktentwicklung_summary: [
        {
            ges: {
                result: "87.7"
            },
            theme: "Produktentwicklung"
        }
    ]
  }
}

我的输出应该是这样的:

{ "marketing" => [
    {
      id: 68,
      projectno: "15",
    },
    {
      ges: { 
        result: "47.6"
      },
      theme: "Marketing"
    }
  ],
  "Produktentwicklung" => [
    {
      id: 68,
      projectno: "15"
    },
    {
      id: 4,
      projectno: "3",
    },
    {
      ges: {
        result: "87.7"
      },
      theme: "Produktentwicklung"
    }
  ]
}

代码:

def year_overview_theme
  branch_hash = {}
  @themes_data.each do |td|
    arr = []
    td[1].map do |dt|
      arr << [{content: dt[:projectno], size: 5, align: :right, background_color: 'D8E5FF'}]
    end
    branch_hash["#{td[0]}"] = arr
  end
  branch_hash
end

问题是它没有迭代正确的哈希键。

例如,我想喜欢:

marketing + marketing_summary 为 1 个哈希值,类似

Produktentwicklung = Produktentwicklung_summary 作为一个哈希,但我的逻辑存在一些问题。

有没有一种方法可以在 2 次迭代后进行检查,

它应该做 arr

【问题讨论】:

  • 我编辑只是为了更正输入哈希并重新格式化输出哈希。

标签: ruby-on-rails ruby hash-of-hashes


【解决方案1】:

所需的哈希可以如下构造。

h[:themes_data].each_with_object({}) { |(k,v),g| 
  g.update(k.to_s[/[^_]+/]=>v) { |_,o,n| o+n } }
  #=> { "Marketing"=>[
  #       {:id=>68, :projectno=>"15"},
  #       {:ges=>{:result=>"47.6"}, :theme=>"Marketing"}
  #     ],
  #     "Produktentwicklung"=>[
  #       {:id=>68, :projectno=>"15"},
  #       {:id=>4, :projectno=>"3"},
  #       {:ges=>{:result=>"87.7"}, :theme=>"Produktentwicklung"}
  #     ]
  #   } 

这使用Hash#update(又名merge)的形式,它使用一个块来确定在被合并的两个散列中存在的键的值。这里的块是:

{ |_,o,n| o+n }

第一个块变量_ 是公共键。我用下划线(一个有效的局部变量)表示它,告诉读者它没有用于块计算。这是常见的做法。其他两个块变量on 的值在方法update 的链接中进行了说明。

正则表达式/[^_]+/,匹配字符串开头的一个或多个不是(^)下划线的字符。当与方法String#[]一起使用时,我们得到:

"Marketing"[/[^_]+/]         #=> "Marketing"
"Marketing_summary"[/[^_]+/] #=> "Marketing" 

【讨论】:

  • 非常感谢您提供如此精彩的回答和解释。我真的很喜欢你的回答,我很谦卑你回答了我的问题。 :)
【解决方案2】:

让我从一个注释开始:在我看来,这更像是应该在 SQL(如果它来自 SQL)而不是 Ruby 中解决的问题。

除此之外,这里有一个可行的解决方案:

output = {}

themes_data.each do |theme, projects|
  projects.each do |project|
    key = project[:theme] || theme.to_s
    output[key] ||= [] # make sure the target is initialized
    output[key] << project
  end
end

使用reduceeach_with_object 可能会有更优雅的解决方案,但这很有效,而且很简单。

【讨论】:

    【解决方案3】:
    keys = themes_data.keys
    summary_keys = themes_data.keys.grep(/_summary/)
    
    result = {}.tap do |hash|
      (keys - summary_keys).each do |key|
        hash[key] = themes_data[key] + themes_data["#{key}_summary".to_sym]
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2013-09-15
      • 2013-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多