2

I have this data for a project with a friend:

arr = [{'Key':'Key 1', 'SecondKey':'SecondKey 1', 'ThirdKey':'Thirdkey 1', 'Value':100},
   {'Key':'Key 1', 'SecondKey':'SecondKey 1', 'ThirdKey':'ThirdKey 2', 'Value':130},
   {'Key':'Key 1', 'SecondKey':'SecondKey 2', 'ThirdKey':'ThirdKey 1', 'Value':230},
   {'Key':'Key 1', 'SecondKey':'SecondKey 2', 'ThirdKey':'ThirdKey 2', 'Value':300},
   {'Key':'Key 2', 'SecondKey':'SecondKey 4', 'ThirdKey':'ThirdKey 1', 'Value':111},
   {'Key':'Key 2', 'SecondKey':'SecondKey 2', 'ThirdKey':'ThirdKey 2', 'Value':400},
   {'Key':'Key 2', 'SecondKey':'SecondKey 1', 'ThirdKey':'ThirdKey 2', 'Value':230}
   ] 

I tried functions like this:

def array_to_dict(arr, classification):
    dct = tree()
    for d in arr:
        dct[d["Key"]]=(d)
    pprint.pprint(dct)

def tree():
    return defaultdict(tree)

def array_to_dict_recursive(arr, classification):
    result = defaultdict(arr)
    for v, k in arr:
        result[k].append(v)
    final_result = [{'type': k, 'items': v} for k, v in result.items()]
    print (str(final_result))

def array_cool(arr):
    #pprint.pprint(arr)
    arr.sort(key=operator.itemgetter('Key'))
    pprint.pprint(arr)
    list1= []
    print("")
    for key, items in itertools.groupby(arr, operator.itemgetter('Key')):
        list1.append(list(items))
    pprint.pprint(list1)

And I want it to appear like a JSON file in this way:

{
"Key 1": {
    "SecondKey 2": {
        "ThirdKey 2": [
            {
                "Key": "Key 1",
                "Value": 300,
                "SecondKey": "SecondKey 2",
                "ThirdKey": "ThirdKey 2"
            }
        ],
        "ThirdKey 1": [
            {
                "Key": "Key 1",
                "Value": 230,
                "SecondKey": "SecondKey 2",
                "ThirdKey": "ThirdKey 1"
            }
        ]
    },
    "SecondKey 1": {
        "ThirdKey 2": [
            {
                "Key": "Key 1",
                "Value": 130,
                "SecondKey": "SecondKey 1",
                "ThirdKey": "ThirdKey 2"
            }
        ],
        "ThirdKey 1": [
            {
                "Key": "Key 1",
                "Value": 100,
                "SecondKey": "SecondKey 1",
                "ThirdKey": "ThirdKey 1"
            }
        ]
    }
},
"Key 2": {
    "SecondKey 4": {
        "ThirdKey 1": [
            {
                "Key": "Key 2",
                "Value": 111,
                "SecondKey": "SecondKey 4",
                "ThirdKey": "ThirdKey 1"
            }
        ]
    },
    "SecondKey 2": {
        "ThirdKey 2": [
            {
                "Key": "Key 2",
                "Value": 400,
                "SecondKey": "SecondKey 2",
                "ThirdKey": "ThirdKey 2"
            }
        ]
    },
    "SecondKey 1": {
        "ThirdKey 2": [
            {
                "Key": "Key 2",
                "Value": 230,
                "SecondKey": "SecondKey 1",
                "ThirdKey": "ThirdKey 2"
            }
        ]
    }
}

}

I tried sorting, but sorting puts the Key in the second position and mess with the next sorting process, and it's not working.

9
  • What hotel? Objects are not guaranteed ordered, only the arrays are. Commented Feb 8, 2017 at 20:39
  • I tried things like this def array_to_dict_recursive(arr, classification): result = defaultdict(arr) for v, k in arr: result[k].append(v) final_result = [{'type': k, 'items': v} for k, v in result.items()] print (str(final_result)) Commented Feb 8, 2017 at 20:40
  • Why don't you just json.dump it? Commented Feb 8, 2017 at 20:41
  • In your question, clearly articulate how you want the data to be sorted and show any code that you've tried so far. I don't see the pattern in what you're trying to do. Commented Feb 8, 2017 at 20:43
  • 1
    What result do you expect, and why do you expect it, and what do you get instead? Again, JS objects aren't ordered, and neither are Python dictionaries. Commented Feb 8, 2017 at 20:49

3 Answers 3

1

Python dicts are unsorted. You have a few options.

Use a tool that applies sorting to a standard dict, example:

import json
print json.dumps(thedict, indent=4, sort_keys=True)

Use a type that maintains the order of creation of dict entries:

from collections import OrderedDict
d = OrderedDict()
d[KEY] = VALUE
d[KEY][SUBKEY] = VALUE
etc.

Or easiest of all, just add them to the array / list in the first place in the order you want them.

Sign up to request clarification or add additional context in comments.

Comments

1

Try

print json.dumps(arr, indent=4, sort_keys=True)

See the json.dumps documentation for more information:

json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)

2 Comments

Hi, this is a sample of the output I got (too big to put here): '[{"Key": "Key 1", "SecondKey": "SecondKey 1", "ThirdKey": "ThirdKey 1", ' '"Value": 100} It's not like a wanted but is a first step
I forgot to add indent=4 to the json.dumps call.
0

Here's a first stab at what you want. It'll get you started and then you can simplify it and make it pretty. Key points:

  • json.dumps() outputs dictionary keys in the order seen, so an explicitly ordered OrderedDict is probably your only way to get that.
  • your result is a different data structure than your input, so you have to build it
  • Dictionaries in Python and JSON do not have ordered keys. So, the moment you import the result into something else, the order is probably lost.
  • This code is really inefficient and will probably perform badly on large data sets.

Your data structure:

  • dicts for each Key, sorted in order
    • dict for each SecondKey, sorted in reverse
      • dict for each ThirdKey, sorted in reverse
        • a list containing a dict for each value (no sorting of values) with these sorted keys and values
          • Key1: Key value from outer loop
          • Value: value for current item
          • SecondKey: SecondKey value from outer loop
          • ThirdKey: ThirdKey value from outer loop

.

from collections import OrderedDict
import json

arr = [{'Key':'Key 1', 'SecondKey':'SecondKey 1', 'ThirdKey':'ThirdKey 1', 'Value':100},
    {'Key':'Key 1', 'SecondKey':'SecondKey 1', 'ThirdKey':'ThirdKey 2', 'Value':130},
    {'Key':'Key 1', 'SecondKey':'SecondKey 2', 'ThirdKey':'ThirdKey 1', 'Value':230},
    {'Key':'Key 1', 'SecondKey':'SecondKey 2', 'ThirdKey':'ThirdKey 2', 'Value':300},
    {'Key':'Key 2', 'SecondKey':'SecondKey 4', 'ThirdKey':'ThirdKey 1', 'Value':111},
    {'Key':'Key 2', 'SecondKey':'SecondKey 2', 'ThirdKey':'ThirdKey 2', 'Value':400},
    {'Key':'Key 2', 'SecondKey':'SecondKey 1', 'ThirdKey':'ThirdKey 2', 'Value':230}
    ]

def arr_to_ordereddict():
    d = OrderedDict()
    keys = set(a['Key'] for a in arr)
    #print(sorted(keys))
    for k1 in sorted(keys):
        k1_dict = OrderedDict()
        d[k1] = k1_dict
        arr2 = [a for a in arr if a['Key'] == k1]
        keys2 = set(a['SecondKey'] for a in arr2)
        #print('\t', k1, sorted(keys2, reverse=True))
        for k2 in sorted(keys2, reverse=True):
            k2_dict = OrderedDict()
            k1_dict[k2] = k2_dict
            arr3 = [a for a in arr if a['SecondKey'] == k2]
            keys3 = set(a['ThirdKey'] for a in arr3)
            #print('\t\t', k1, k2, sorted(keys3, reverse=True))
            for k3 in sorted(keys3, reverse=True):
                k3_list = []
                k2_dict[k3] = k3_list
                for item in (a for a in arr3 if a['ThirdKey'] == k3):
                    value_dict = OrderedDict()
                    value_dict['Key'] = k1
                    value_dict['Value'] = item['Value']
                    value_dict['SecondKey'] = k2
                    value_dict['ThirdKey'] = k3
                    k3_list.append(value_dict)
    return d

print(json.dumps(arr_to_ordereddict(), indent=4))

1 Comment

Hi! Thanks for the help @Harvey , I will try to simplify, and also I want to make a recursive version, but this is a great start for me :D Thanks again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.