【问题标题】:Create nested json like flare.json using ruby使用ruby创建像flare.json这样的嵌套json
【发布时间】:2017-02-12 09:26:00
【问题描述】:

我想使用 d3 创建一些需要我构建 json 的可视化。我一直在使用 ruby​​ 进行此操作,但由于 json 可以嵌套超过 2 个级别,因此我在减少代码重复方面遇到了麻烦。这是我获得的用于 2 级嵌套的代码..

    level1, level2 = Array.new(2) { [] }
    array.each do |arrayItem|
        level1.push(arrayItem[:key1])
        level2.insert(-1, {
            label: arrayItem[:key2],
            parent: arrayItem[:key1],
            value: arrayItem[:value],
            })
    end 
    index1 = index2 = 0
    tempLevel1 = []
    main = Hash.new()
    main["name"] = "flare"
    main["children"] = []
    while( index1 < level1.size ) do
        index2 = 0
        level1Value = level1[index1]
        level1Row = Hash.new()
        level1Row["name"] = level1Value
        level1Row["children"] = []
        tempLevel2 = []
        while( index2 < level2.size ) do 
            level2Value = level2[index2][:label]
            level2Parent = level2[index2][:parent]
            level2Count = level2[index2][:value]
            if( level2Parent == level1Value )
                level2Row = Hash.new()
                if( level2Value.nil? )
                    level2Row["name"] = "Others"
                else
                    level2Row["name"] = level2Value
                end
                level2Row["size"] = level2Count
                tempLevel2 << level2Row
            end
            index2 += 1
        end
        if( !tempLevel2.empty? )
            level1Row["children"] = level1Row["children"] | tempLevel2
            tempLevel1 << level1Row
        end
        index1 += 1
    end
    main["children"] = main["children"] | tempLevel1
    return main

正如您想象的那样,可以有多个级别,这通常意味着更多的嵌套循环,这也会增加代码大小。有没有办法减少这种代码重复以及嵌套循环的数量。

输入数组将是这样的..

{:key1=>"a", :key2=>"p", :value=>1}
{:key1=>"a", :key2=>"q", :value=>1}
{:key1=>"a", :key2=>"r", :value=>1}
{:key1=>"b", :key2=>"s", :value=>1}
{:key1=>"c", :key2=>"q", :value=>1}
{:key1=>"a", :key2=>"t", :value=>1}

输出应该是这样的..

{
"name": "flare",
"children": [
    {
        "name": "a",
        "children": [
            {
                "name": "p",
                "size": 1
            },
            {
                "name": "q",
                "size": 1
            },
            {
                "name": "r",
                "size": 1
            },
            {
                "name": "s",
                "size": 1
            }
        ]
    },
    {
        "name": "b",
        "children": [
            {
                "name": "t",
                "size": 1
            }
        ]
    },
    {
        "name": "c",
        "children": [
            {
                "name": "q",
                "size": 1
            }
        ]
    }
]

}

【问题讨论】:

    标签: json ruby code-duplication


    【解决方案1】:

    不确定我是否正确。据我了解,您想从普通数组构建嵌套树结构。在 ruby​​ 中,您可以使用 hash 中的引用来发挥自己的优势。

    require 'json'
    
    array = [
      {key1: 'a', key2: nil, value: 1},
      {key1: 'b', key2: 'a', value: 1},
      {key1: 'c', key2: 'a', value: 1},
      {key1: 'd', key2: 'b', value: 1},
      {key1: 'e', key2: nil, value: 1},
      {key1: 'f', key2: 'b', value: 1},
    ]
    
    # build hash table to keep references on values
    hashtable = {}
    array.each do |item|
      hashtable[item[:key1]] = {
        name: item[:key1],
        children: [],
        size: item[:value]
      }
    end
    
    # build json data based on hashtable
    json_hash = {
      name: 'flare',
      children: []
    }
    array.each do |item|
      if item[:key2].nil?
        json_hash[:children] << hashtable[item[:key1]]
      else
        hashtable[item[:key2]][:children] << hashtable[item[:key1]]
      end
    end
    
    jj json_hash
    

    【讨论】:

    • 我已经编辑了这个问题以便更好地理解。我认为您提供的解决方案也很接近,但只是叶节点应该具有值,而内部节点不应具有 size 属性。我也不确定当说我有 3 个级别时它是否可以工作,即 key1、key2、key3
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 2018-09-05
    • 2017-07-18
    • 2021-02-03
    • 2011-12-15
    相关资源
    最近更新 更多