2013-03-06 2 views
2

У меня есть объект JSON, который выглядит следующим образом:Свести объект JSON с другой встроенной JSON объектов

 
{ 
    "name":"bacon" 
    "category":["food","meat","good"] 
    "calories":"huge" 
} 

Я пытаюсь выпрямиться, что в массив уникальных значений. Мне нужно создать таблицу фактов для Tableau, которая не может напрямую работать с данными с несколькими таблицами или данными JSON.

Я не придирчива к тому, делаю ли я это на Python или Ruby, но до сих пор я пытался это сделать в Ruby. Я могу легко разобрать JSON и получить из него хэнд Ruby, который кажется правильным, что нужно сделать в первую очередь.

 
{"name"=>"bacon", "category"=>["food", "meat", "good"], "calories" => "huge"} 

и мне нужно, чтобы произвести это:

name,category,calories 
bacon,food,huge 
bacon,meat,huge 
bacon,good,huge 

Так что я думаю, что нужно перебрать, что хэш и попытаться не-гнездо его. Я экспериментировал с чем-то вроде этого:

def Flatten(inHash) 
    inHash.each do |key,value| 
     if value.kind_of?(Hash) 
      Flatten(value) 
     else 
      puts "#{value}" 
     end 
    end 
end 

Но и это, кажется, чтобы напечатать все значения, но она не повторяет значение, которое было до. Таким образом, я получаю вывод, который выглядит как

bacon 
food 
meat 
good 
huge 

Есть встроенный метод или драгоценный камень или библиотека, которая будет это или я смотрю на строительство с нуля? Любые идеи о том, как получить результат, который я хочу? Я говорю Ruby и Python, поэтому, если у вас есть ответ на Python, пожалуйста, поделитесь.

+0

Is '{" name ":" bacon "" category ": [" food "," meat "," good "]" calories ":" огромный "}' действительный объект json в Python? – Sibi

ответ

2
>>> #Assuming your json data is correctly formatted as is as follows 
>>> data = '{ "name":"bacon", "category":["food","meat","good"], "calories":"huge" }' 
>>> #Lets call our json parser as foo (I am bad with names) 
>>> def foo(data): 
    #You first need to parse it to a Py Object 
    json_data = json.loads(data) 
    from collections import namedtuple 
    #Now create a namedtuple with the given keys of the dictionary 
    food_matrix = namedtuple('food_matrix',json_data.keys()) 
    #And create a tuple out of the values 
    data_tuple = food_matrix(*json_data.values()) 
    #Now with itertools.product create a cross product 
    from itertools import product 
    data_matrix = list(product([data_tuple.name],data_tuple.category, [data_tuple.calories])) 
    # Now display the heading 
    print "{:15}{:15}{:15}".format(["name","category","calories") 
    # Now display the values 
    for e in data_matrix: 
     print "{:15}{:15}{:15}".format(*e) 


>>> #Now call it 
>>> foo(data) 
name   category  calories     
bacon   food   huge   
bacon   meat   huge   
bacon   good   huge   
>>> 
0

Предполагая, что ваш JSON имеет запятые (чтобы сделать его valid JSON), вы можете использовать itertools.product перечислить все возможные комбинации:

import itertools as IT 
import json 

text = '{ "name":"bacon", "category":["food","meat","good"], "calories":"huge" }' 
data = json.loads(text) 

# Sort the keys in the order they appear in `text` 
keys = sorted(data.keys(), key = lambda k: text.index(k)) 

# Promote the values to lists if they are not already lists 
values = [data[k] if isinstance(data[k], list) else [data[k]] for k in keys] 

print(','.join(keys)) 
for row in IT.product(*values): 
    print(','.join(row)) 

урожаи

name,category,calories 
bacon,food,huge 
bacon,meat,huge 
bacon,good,huge 
0

Вот бы мое решение:

require 'json' 

# Given a json object 
json = JSON.parse('{"name":"bacon", "category":["food","meat","good"], "calories":"huge"}') 

# First, normalize all the values to arrays 
hash = Hash[json.map{|k, v| [k, [v].flatten]}] 

# We now have a hash like {"name" => ["bacon"], ...} 

# Then we'll make the product of the first array of values 
# (in this case, ["bacon"]) with the other values 
permutations = hash.values[0].product(*hash.values[1..-1]) 

# Now just need to output 
puts hash.keys.join(",") 
permutations.each{ |group| puts group.join(",") } 
+0

Обратите внимание, что это будет работать только в Ruby 1.9+, потому что он принимает заданный хеш. Вы можете добиться такого же результата в Ruby 1.8, пропустив преобразование преобразования хэша и используя массивы типа '[" name ", [" bacon "]]' – gmalette

Смежные вопросы