Ruby - 如何将大型多维哈希数组转换为 CSV 格式

标签 ruby csv multidimensional-array hash

我有一个相当大的哈希数组(存储在“@hash["response"]["results"])”中,由我的程序以 JSON 格式返回。

我在 Stack Overflow 上看到了几个关于如何将简单哈希转换为 CSV 格式的示例,但是我还没有找到任何使用更大数据集执行此操作的复杂示例。

我想使用哈希键("pluginID""ip""pluginName" 等)作为CSV header 和哈希值("11112""100.100.100.100""此处插件的名称" 等) CSV 行内容。

请注意,“repository” 键本身就是一个哈希值,因此我只想使用名称,而不是 ID 或描述。

非常感谢任何帮助。我已经按照 Ruby CSV 标准库说明使用了一些代码示例,但我什至还没有接近。

@hash = '{
  "type": "regular",
  "response": {
    "Records": "137",
    "rRecords": 137,
    "startOffset": "0",
    "endOffset": "500",
    "matchingDataElementCount": "-1",
    "results": [
      { "pluginID": "11112",
        "ip": "100.100.100.100",
        "pluginName": "Name for plugin here",
        "firstSeen": "1444208776",
        "lastSeen": "1451974232",
        "synopsis": "synopsis contents",
        "description": "Full description would go here... Full description would go here... Full description would go here... Full description would go here... Full description would go here...",
        "solution": "",
        "version": "Revision: 1.51",
        "pluginText": "output text here",
        "dnsName": "name",
        "repository": {
          "id": "1",
          "name": "Name Here As Well",
          "description": "Description here also"
        },
        "pluginInfo": "11112 (0/6) Name for plugin here"
      },
      { "pluginID": "11113",
        "ip": "100.100.100.100",
        "pluginName": "Name for plugin here",
        "firstSeen": "1444455329",
        "lastSeen": "1451974232",
        "synopsis": "Tsynopsis contents",
        "description": "Full description would go here... Full description would go here... Full description would go here... Full description would go here... Full description would go here...",
        "solution": "",
        "version": "Revision: 1.51",
        "pluginText": "output text here",
        "dnsName": "name here",
        "repository": {
          "id": "1",
          "name": "Name Here As Well",
          "description": "Description here also"
        },
        "pluginInfo": "11112 (0/6) Name for plugin here"
      },
      { "pluginID": "11113",
        "ip": "100.100.100.100",
        "pluginName": "Name for plugin here : Passed",
        "firstSeen": "1444455329",
        "lastSeen": "1444455329",
        "synopsis": "nope, more synopsis data here",
        "description": "Uanother different description",
        "solution": "",
        "version": "Revision: 1.14",
        "pluginText": "",
        "dnsName": "name here",
        "repository": {
          "id": "1",
          "name": "Name Here As Well",
          "description": "Description here also"
        },
        "pluginInfo": "11114 (0/6) Name for plugin here : Passed"
      },
      { "pluginID": "11115",
        "ip": "100.100.100.100",
        "pluginName": "Name for plugin here",
        "firstSeen": "1444455329",
        "lastSeen": "1444455329",
        "synopsis": "Tsynopsis contents",
        "description": "Full description would go here... Full description would go here... Full description would go here... Full description would go here... Full description would go here...",
        "solution": "",
        "version": "Revision: 1.51",
        "pluginText": "output text here",
        "dnsName": "",
        "repository": {
          "id": "1",
          "name": "Name Here As Well",
          "description": "Description here also"
        },
        "pluginInfo": "11116 (0/6) Name for plugin here"
      }
    ]
  },
  "code": 0,
  "msg": "",
  "msg_det": [],
  "time": 1454733549
}'

最佳答案

这很简单。基本上有五个步骤:

  1. 将 JSON 解析为 Ruby 哈希。
  2. “results”数组中的第一个哈希中获取键名称,并将其作为标题写入 CSV 文件。
  3. 迭代“results”数组和每个哈希:

    1. “repository” 哈希值替换为其“name” 值。
    2. 按照与标题相同的顺序提取值并将其写入 CSV 文件。

代码看起来像这样:

require 'json'
require 'csv'

json = '{
  "type": "regular",
  "response": {
    ...
  },
  ...
}'

# Parse the JSON
hash = JSON.parse(json)

# Get the Hash we're interested in
results = hash['response']['results']

# Get the key names to use as headers
headers = results[0].keys

filename = "/path/to/output.csv"

CSV.open(filename, 'w', headers: :first_row) do |csv|
  # Write the headers to the CSV
  csv << headers

  # Iterate over the "results" hashes
  results.each do |result|
    # Replace the "repository" hash with its "name" value
    result['repository'] = result['repository']['name']

    # Get the values in the same order as the headers and write them to the CSV
    csv << result.values_at(*headers)
  end
end

此代码 (headers = results[0].keys) 假设第一个 "results" 哈希将包含所有CSV 中您想要的键。如果不是这种情况,您需要:

  1. 明确指定 header ,例如:

    headers = %w[ pluginId ip pluginName ... ]
    
  2. 循环所有哈希并构建所有键的列表:

    headers = results.reduce([]) {|all_keys, result| all_keys | result.keys }
    

关于Ruby - 如何将大型多维哈希数组转换为 CSV 格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35356735/

相关文章:

ruby - 我需要从查询结果中获取用户 ID

ruby-on-rails - 仅允许用户在 Rails 中输入字母和数字

android - Android中sqlite数据库如何插入大量数据

ruby-on-rails - 在 Rails 中为 Controller 设置默认页面

ruby-on-rails - rails bundle 清洁

csv - 使用经典的 asp (vbscript) 从 csv 字符串中删除不需要的 chr(13)

C# 异常处理继续出错

php多维数组获取值

php - 如何将 mysql 连接结果包含到 PHP 多维数组中

php - 按数组值对多维数组进行排序