0

I have an array of JSON objects from which I want to create a "single JavaScript object." I'd appreciate ideas in Python or JavaScript. In fact, I am not even sure what the proper terminology is to describe (or Google) this kind of question. Thanks!

The original list looks like this:

[
{
    "State_Code": "01",
    "County_Code": "000",
    "State_Abbrv": "AL",
    "County_Name": "ALABAMA",
    "DATA": "12345"

},
{
    "State_Code": "01",
    "County_Code": "001",
    "State_Abbrv": "AL",
    "County_Name": "AUTAUGA COUNTY",
    "DATA": "123"

},
{
    "State_Code": "01",
    "County_Code": "003",
    "State_Abbrv": "AL",
    "County_Name": "BALDWIN COUNTY",
    "DATA": "321"

},
{
    "State_Code": "02",
    "County_Code": "000",
    "State_Abbrv": "AK",
    "County_Name": "ALASKA",
    "DATA": "98765"

},
{
    "State_Code": "02",
    "County_Code": "013",
    "State_Abbrv": "AK",
    "County_Name": "ALEUTIANS EAST BOROU",
    "DATA": "456"

},

..............  ]

And I want it to look like this:

{
    "name": "USA",
    "children": [
        {
            "name": "ALABAMA",
            "children": [
                {
                    "name": "AUTAUGA COUNTY",
                    "DATA": 123
                },
                {
                    "name": "BALDWIN COUNTY",
                    "DATA": 321
                }
            ]
        },
        {
            "name": "ALASKA",
            "children": [
                {
                    "name": "ALEUTIANS EAST BOROU",
                    "DATA": 456
                }
            ]
        }
        .............
    ]
}

I am attempting to use a Python loop like this kind of idea (apologies for any typos, will fix tonight):

runningListCounty = []
tempD = defaultdict(dict)
tempDCounty = defaultdict(dict)
i = 0
for l in listOfJson:
  if l['County_Code'] == '000'
      tempD['name'] = l['County_Name']
      if i > 0: #only do this after the first loop
         tempD['children'] = runningListCounty 
         runningList.append(tempD)       
         runningListCounty = []
         tempD = defaultdict(dict)
  else:
      tempDCounty = defaultdict(dict)
      tempDCounty['name'] = l['County_Name']
      tempDCounty['DATA'] = l['DATA']
      runningListCounty.append(tempDCounty)
  i = i + 1
MrCode
  • 63,975
  • 10
  • 90
  • 112
mgcdanny
  • 1,082
  • 1
  • 13
  • 20
  • [There's no such thing as a "JSON Object"](http://benalman.com/news/2010/03/theres-no-such-thing-as-a-json/). I think you want a JavaScript object instead. – Marcel Korpel Feb 11 '13 at 16:42
  • Could you please explain how they're linked? If something has a county code of 000, it's a state, but what qualifies a country? Are counties linked by state abbreviaton or code to their state? – Bergi Feb 11 '13 at 16:44
  • "State_Code" is just a numerical version of "State_Abbrv". Counties are linked to State by State_Code (or Abbrv) and have a County_Code other than '000' – mgcdanny Feb 11 '13 at 17:18

3 Answers3

0

Using guess work an attempt would be.

data = [
{
    "State_Code": "01",
    "County_Code": "000",
    "State_Abbrv": "AL",
    "County_Name": "ALABAMA",
    "DATA": "12345"

},
{
    "State_Code": "01",
    "County_Code": "001",
    "State_Abbrv": "AL",
    "County_Name": "AUTAUGA COUNTY",
    "DATA": "123"

},
{
    "State_Code": "01",
    "County_Code": "003",
    "State_Abbrv": "AL",
    "County_Name": "BALDWIN COUNTY",
    "DATA": "321"

},
{
    "State_Code": "02",
    "County_Code": "000",
    "State_Abbrv": "AK",
    "County_Name": "ALASKA",
    "DATA": "98765"

},
{
    "State_Code": "02",
    "County_Code": "013",
    "State_Abbrv": "AK",
    "County_Name": "ALEUTIANS EAST BOROU",
    "DATA": "456"

}
]


roots = [ d for d in data if d['County_Code'] == '000']

def crawl(data, roots):
    for root in roots:
        yield {
            'name' : root['County_Name'],
            'children' : [{ 'name' : d['County_Name'], 'DATA' : d['DATA'] }
                for d in data if d['County_Code'] != '000' and d['State_Code'] == root['State_Code']]
        }


final = { 'name' : 'USA', 'children' : [ x for x in crawl(data, roots)]}

import pprint

pprint.pprint(final)

Gives:

{'children': [{'children': [{'DATA': '123', 'name': 'AUTAUGA COUNTY'},
                            {'DATA': '321', 'name': 'BALDWIN COUNTY'}],
               'name': 'ALABAMA'},
              {'children': [{'DATA': '456', 'name': 'ALEUTIANS EAST BOROU'}],
               'name': 'ALASKA'}],
 'name': 'USA'}
sotapme
  • 4,695
  • 2
  • 19
  • 20
  • Wow, this is awesome. Why did you use yield? – mgcdanny Feb 12 '13 at 14:33
  • Force of habit. Building a big dict in ``crawl`` would be inefficient and actually the code would be more complicated. Also without using ``yield`` you'd be imposing on the caller that you would return a list of dicts. – sotapme Feb 12 '13 at 17:42
0

Javascript solution:

Demo

var data = [
{
    "State_Code": "01",
    "County_Code": "000",
    "State_Abbrv": "AL",
    "County_Name": "ALABAMA",
    "DATA": "12345"

},
{
    "State_Code": "01",
    "County_Code": "001",
    "State_Abbrv": "AL",
    "County_Name": "AUTAUGA COUNTY",
    "DATA": "123"

},
{
    "State_Code": "01",
    "County_Code": "003",
    "State_Abbrv": "AL",
    "County_Name": "BALDWIN COUNTY",
    "DATA": "321"

},
{
    "State_Code": "02",
    "County_Code": "000",
    "State_Abbrv": "AK",
    "County_Name": "ALASKA",
    "DATA": "98765"

},
{
    "State_Code": "02",
    "County_Code": "013",
    "State_Abbrv": "AK",
    "County_Name": "ALEUTIANS EAST BOROU",
    "DATA": "456"

}
];

var newData = { name : 'USA', children : [] };

for(var i=0; i<data.length; i++) {
    if(data[i].County_Code == "000") {
        newData.children.push({ name : data[i].County_Name, state_code : data[i].State_Code, children : [] });
    }
}

for(var i=0; i<data.length; i++) {
    if(data[i].County_Code != "000") {
        for(var x=0; x<newData.children.length; x++) {
            if(data[i].State_Code == newData.children[x].state_code) {
                newData.children[x].children.push({ name : data[i].County_Name, data : data[i].DATA });
            }
        }
    }
}

console.log(newData); // or convert to JSON with  JSON.stringify(newData)

The result newData is:

{
    "name": "USA",
    "children": [
        {
            "name": "ALABAMA",
            "state_code": "01",
            "children": [
                {
                    "name": "AUTAUGA COUNTY",
                    "data": "123"
                },
                {
                    "name": "BALDWIN COUNTY",
                    "data": "321"
                }
            ]
        },
        {
            "name": "ALASKA",
            "state_code": "02",
            "children": [
                {
                    "name": "ALEUTIANS EAST BOROU",
                    "data": "456"
                }
            ]
        }
    ]
}
MrCode
  • 63,975
  • 10
  • 90
  • 112
-1

Javascript Solution

Here's the fiddle: JSFIDDLE

Here's the code:

var statesObj = JsonSource,
    finalObj = {
        USA : {
            name: "USA",
            children: []
        }
    };
for (var st = 0; st < statesObj.length; ++st) {
    // First the states
    if( statesObj[st].County_Code === "000") {
        var newState = {
            name: statesObj[st].County_Name,
            abbrv: statesObj[st].State_Abbrv,
            children: []
        };
        finalObj.USA.children.push(newState);
    }
}

for (var st = 0; st < statesObj.length; ++st) {
    // Now the rest
    if( statesObj[st].County_Code !== "000") {
        var newChild = {
            name: statesObj[st].County_Name,
            data: statesObj[st].DATA
        };
        for (var sub in finalObj.USA.children) {
            if (finalObj.USA.children.hasOwnProperty(sub) &&
                finalObj.USA.children[sub].abbrv === statesObj[st].State_Abbrv) {
                finalObj.USA.children[sub].children.push(newChild);
                break;
            }
        }
    }
}

var finalJson = JSON.stringify(finalObj);
console.log(finalJson);
Tivie
  • 18,864
  • 5
  • 58
  • 77
  • 1
    Always check for `hasOwnProperty` in `for … in` loops when looping over object properties. – Marcel Korpel Feb 11 '13 at 17:25
  • @MarcelKorpel Thanks for pointing it out. I didn't add it because it seemed OP wanted a one time run program – Tivie Feb 11 '13 at 17:48
  • @MarcelKorpel: Always? No, then you must have some misconceptions about this. Especially when you have a plain JSON-parsed object or a literal it's absolutely not necessary. – Bergi Feb 11 '13 at 18:06
  • 2
    @Tivie: [Never use for-in-loops with Arrays!!](http://stackoverflow.com/questions/500504/javascript-for-in-with-arrays) – Bergi Feb 11 '13 at 18:09
  • @Bergi: I learned that `Object.prototype` might have been changed and when iterating over objects you will find those additions, too. – Marcel Korpel Feb 12 '13 at 11:26
  • @MarcelKorpel: No one right-minded adds enumerable properties to `Object.prototype`. If someone does, don't use that code. – Bergi Feb 12 '13 at 13:34