【问题标题】:How to get the right csv format from hash in ruby如何从 ruby​​ 中的哈希中获取正确的 csv 格式
【发布时间】:2015-09-18 16:47:41
【问题描述】:

散列到 csv

哈希:

{
"employee" => [
  {
    "name" => "Claude",
    "lastname"=> "David",
    "profile" => [
       "age" => "43",
       "jobs" => [
         {
           "name" => "Ingeneer",
           "year" => "5"
         }
       ],
       "graduate" => [
          {
             "place" => "Oxford",
             "year" => "1990"
          },
       ],
       "kids" => [
         {
           "name" => "Viktor",
           "age" => "18",
         }
    ]
  }
}]

这是我将处理的哈希示例。所以,如你所见,其中有很多层级的数组。

我的问题是,如何正确地将其放入 CSV 文件中?

我试过这个:

column_names = hash['employee'].first.keys
s=CSV.generate do |csv|
   csv << column_names
   hash['scrap'].each do |x|
     csv << x.values
   end
end
File.write('myCSV.csv', s)

但我只得到namelastnameprofile 作为键,当我会捕获所有它们时(agejobsnameyeargraduate、@ 987654332@...)。

此外,如何将每个案例关联一个值? 因为我实际上拥有所有 employee[x] 一个单独的单元格。有没有我遗漏的参数?

Ps:这可能是this post的以下内容

【问题讨论】:

  • 我的建议是不要从那个哈希开始。从创建哈希的同一源创建 CSV。

标签: ruby csv hash


【解决方案1】:

有效的 CSV 输出具有固定数量的列,您的散列具有可变数量的值。 jobsgraduatekids 键都可以有多个值。

如果您的唯一目标是生成可以在 Excel 中读取的 CSV 输出,您可以枚举您的 Hash,获取每个键的最大键/值对数,合计,然后写入您的 CSV 输出,填充带有“”的空白值。

Stack Overflow 上有很多例子,搜索“deep hash”开始。

对于您提供的每个哈希,您的结果会有不同数量的列。

如果你问我,那工作量太大了。 如果您只想呈现可读的结果,最好和最简单的选择是将哈希转换为为可读性而创建的 YAML:

require 'yaml'
hash = {.....}
puts hash.to_yaml

employee:
- name: Claude
  lastname: David
  profile:
  - age: '43'
    jobs:
    - name: Ingeneer
      year: '5'
    graduate:
    - place: Oxford
      year: '1990'
    kids:
    - name: Viktor
      age: '18'

【讨论】:

  • 有效的 csv 具有固定数量的列,您的散列具有可变数量的值。好吧,确实我正打算对空单元格(“”)使用您的方法。 deep hash :这完全是我的情况,不知道这个昵称,这对我有很大帮助。对于 yaml 选项,这是一个很好的提示!即使我之前会尝试弄清楚如何解决我的问题,这绝对是我将探索的一种方式。谢谢。
【解决方案2】:

如果您想将哈希转换为 CSV 文件或记录,您需要获得键和值的“平面”表示。类似于以下内容:

h = {
 a: 1,
 b: {
  c: 3,
  d: 4,
  e: {
    f: 5
  },
  g: 6
 } 
}

def flat_keys(h)
  h.keys.reject{|k| h[k].is_a?(Hash)} + h.values.select{|v| v.is_a?(Hash)}.flat_map{|v| flat_keys(v)}
end

flat_keys(h)
# [:a, :c, :d, :g, :f]

def flat_values(h)
  h.values.flat_map{|v| v.is_a?(Hash) ? flat_values(v) : v}
end

flat_values(h)
# [1, 3, 4, 5, 6]

然后您可以应用它来创建 CSV 输出。

【讨论】:

  • 您以非常简单的方式回答了我的问题!谢谢
【解决方案3】:

这取决于这些字段在数据库中的表示方式。

例如,您的jobs 有一个带有name 键的散列,而您的kids 也有一个带有name 键的散列,因此您不能只是“扁平化”它们,因为键必须是唯一的.

jobs 可能是另一个模型(数据库表),因此您可能必须(取决于数据库)单独编写它,包括相关对象的 id 等内容。

你确定你不是在你的头上?从您的最后一个问题来看,因为您似乎将 csv 视为简单的键值对,省略了所有数据库表示和关系。

【讨论】:

  • 如果我真的想将它导出到数据库,我会同意你的看法。但这不是我的目标,我正在用 ruby​​ 练习。现在,我只想匹配 hash 和 csv !
  • 为了更清楚地说明我的观点,我在这里只想导出一个 csv 文件,该文件可由不了解计算机的第三方读取。而且由于我还没有做生意,所以我没有接口数据库/用户。我只是想探索 ruby​​ 能给我带来的一切。
猜你喜欢
  • 1970-01-01
  • 2016-11-02
  • 2015-06-28
  • 1970-01-01
  • 1970-01-01
  • 2010-12-19
  • 1970-01-01
  • 1970-01-01
  • 2017-12-22
相关资源
最近更新 更多