【问题标题】:How could I Turn 2 arrays and 1 hash into single hash by Ruby?如何通过 Ruby 将 2 个数组和 1 个散列转换为单个散列?
【发布时间】:2015-08-19 13:20:50
【问题描述】:

我的问题

在这里,我有 2 个数组和 1 个哈希,

@key_array = %w(year entry amount)

@nums = {
  "sales": [1000, 2000, 3000, 4000],
  "net_income": [20, 30, 50, 60],
}

@years = [2011, 2012, 2013, 2014]

我想做的就是把那三个变成这样

[{"year"=>2011, "entry"=>:sales, "amount"=>1000},
 {"year"=>2012, "entry"=>:sales, "amount"=>2000},
 {"year"=>2013, "entry"=>:sales, "amount"=>3000},
 {"year"=>2014, "entry"=>:sales, "amount"=>4000},
 {"year"=>2011, "entry"=>:net_income, "amount"=>20},
 {"year"=>2012, "entry"=>:net_income, "amount"=>30},
 {"year"=>2013, "entry"=>:net_income, "amount"=>50},
 {"year"=>2014, "entry"=>:net_income, "amount"=>60}]

到目前为止,我已经尝试过这段 Ruby 代码...

def build_entry_nums_hash
  num_arr = []
  @years.each do |year|
    @nums.each do |key, value|
      value.each do |fin|
        value_array = [year, key, fin]
        hash = {}
        @key_array.zip(value_array).each { |k, v| hash[k] = v }
        num_arr << hash
      end
    end
  end
  num_arr
end

它几乎返回了我的预期,但有点错误。它返回一些不必要的哈希。

 [{"year"=>2011, "entry"=>:sales, "amount"=>1000},
 {"year"=>2011, "entry"=>:sales, "amount"=>2000},
 {"year"=>2011, "entry"=>:sales, "amount"=>3000},
 {"year"=>2011, "entry"=>:sales, "amount"=>4000},
 ......
 {"year"=>2014, "entry"=>:net_income, "amount"=>20},
 {"year"=>2014, "entry"=>:net_income, "amount"=>30},
 {"year"=>2014, "entry"=>:net_income, "amount"=>50},
 {"year"=>2014, "entry"=>:net_income, "amount"=>60}]

你能给我一些建议吗?

现状

我不确定这是否有必要,所以如果您担心我为什么必须将这些数组和散列转换为一个散列,请仔细阅读。

我正在尝试使用 Nokogiri 解析来自网站的一些财务数据。数据以 HTML Table 标记编写,看起来像 Excel 电子表格。我的目标是使用我的导轨显示这些数据。目前,我能够获得这些数字,并苦苦挣扎如何将它们放入 Rails DB。如果我能喜欢就好了..

Findata.create{"year"=>2011, "entry"=>:sales, "amount"=>1000} 

因为很容易获得连续的财务数字,我做了一个像@num 这样的哈哈。我需要的是混合其他 2 个数组并获得我需要的哈希值。

编辑:我已经用哈希纠正了数组中的错误

【问题讨论】:

  • 这看起来像是这个问题的重复...stackoverflow.com/questions/5174913/…
  • 为什么您只有 3 个 :sales 条目,而 :net_income 4 个条目 - 这只是一个错误吗?
  • Max,这只是我的错误。我会改正的。

标签: ruby-on-rails arrays ruby hash


【解决方案1】:
arr = []
@nums.each do |num_key, num_arr|
  @years.each_with_index do |year,i|
    arr << {"year" => year, "entry" => num_key.to_sym, "amount" => num_arr[i]}
  end
end;arr

给我

[{"amount"=>20, "entry"=>:net_income, "year"=>2011},
{"amount"=>30, "entry"=>:net_income, "year"=>2012},
{"amount"=>50, "entry"=>:net_income, "year"=>2013},
{"amount"=>60, "entry"=>:net_income, "year"=>2014},
{"amount"=>1000, "entry"=>:sales, "year"=>2011},
{"amount"=>2000, "entry"=>:sales, "year"=>2012},
{"amount"=>3000, "entry"=>:sales, "year"=>2013},
{"amount"=>4000, "entry"=>:sales, "year"=>2014}]

编辑:在循环后面加上“;arr”,这样你就剩下了保存哈希值的arr 变量。

【讨论】:

  • 嗯,技术上上面的代码会返回@nums :) 我认为最好在外循环中使用each_with_object
  • 循环返回什么并不重要:所需的数据保存在变量arr中。如果不清楚,请道歉。
  • 我的意思是,您不需要以局部变量arr 的形式 增加额外的复杂性。您更新的代码将返回该数组。这也是each_with_object 在内部所做的,所以不妨直接使用它(代码会更简洁)
  • Sergio,如果我从 Max 的代码中删除 arr,它只会返回我想要获取的第一个元素。
【解决方案2】:

我重构了 Max 的答案。

  def build_hash
    @nums.flat_map do |num_key, num_arr|
      @years.map.with_index do |year, i|
        {"year" => year, "entry" => num_key.to_sym, "amount" => num_arr[i]}
      end
    end
  end

仅供参考,这是代码和规范。

require 'spec_helper'

describe 'Array to Hash' do
  before do
    @key_array = %w(year entry amount)

    @nums = {
        "sales": [1000, 2000, 3000, 4000],
        "net_income": [20, 30, 50, 60],
    }

    @years = [2011, 2012, 2013, 2014]
  end

  let(:expected) do
    [{"year"=>2011, "entry"=>:sales, "amount"=>1000},
     {"year"=>2012, "entry"=>:sales, "amount"=>2000},
     {"year"=>2013, "entry"=>:sales, "amount"=>3000},
     {"year"=>2014, "entry"=>:sales, "amount"=>4000},
     {"year"=>2011, "entry"=>:net_income, "amount"=>20},
     {"year"=>2012, "entry"=>:net_income, "amount"=>30},
     {"year"=>2013, "entry"=>:net_income, "amount"=>50},
     {"year"=>2014, "entry"=>:net_income, "amount"=>60}]
  end

  def build_hash
    @nums.flat_map do |num_key, num_arr|
      @years.map.with_index do |year, i|
        {"year" => year, "entry" => num_key.to_sym, "amount" => num_arr[i]}
      end
    end
  end

  specify do
    expect(build_hash).to eq expected
  end
end

【讨论】:

    猜你喜欢
    • 2013-05-16
    • 2020-06-29
    • 1970-01-01
    • 2023-03-07
    • 2011-08-21
    • 2019-08-15
    • 2016-09-04
    • 2015-06-12
    • 2014-06-24
    相关资源
    最近更新 更多