Создайте вложенный json, например flash.json, используя ruby

Я хотел создать несколько визуализаций с помощью d3, которые требуют от меня сборки json. Я делал это с помощью ruby, но, поскольку json может быть вложен более чем на 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
            }
        ]
    }
]

}


person Viraj Parimi    schedule 12.02.2017    source источник


Ответы (1)


не совсем уверен, правильно ли я понял. Насколько я понял, вы хотите построить вложенную древовидную структуру из простого массива. В ruby ​​вы можете использовать ссылки в хеше в своих интересах.

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
person insider    schedule 12.02.2017
comment
Я отредактировал вопрос для лучшего понимания. Также решение, которое вы предоставили, я думаю, было близким, но только то, что конечные узлы должны иметь значения, а внутренние узлы не должны иметь атрибут размера. Также я не уверен, что это может работать, когда, скажем, у меня есть 3 уровня, то есть key1, key2, key3. - person Viraj Parimi; 12.02.2017