How can I do to convert OrderedDict to Dict
Asked Answered
C

4

5

I have a this list

a = [OrderedDict([('a','b'), ('c','d'), ('e', OrderedDict([('a','b'), ('c','d') ]))])]

and I want to convert the OrderedDict in dictionary.

Do you know how could I do ?

Thank you !

Changsha answered 7/6, 2019 at 12:25 Comment(5)
This in not a orderddict, but it is a list of tuples, also you could perhaps do dict(a)Jude
Have you tried giving it a go yourself? Perhaps callining the dict constructor?Exploit
you wrote a list here, then asked about converting an OrderedDict in Dictionary? Can you clarify what is it you need? Also, An OrderedDict can behave like a dictionary without issues, is there a particular reason you're looking to convert the OrderedDict?Obituary
What's the expected output here?Jude
An OrderedDict is a dict; in what sense do you need to "convert" it?Garman
A
11

To convert a nested OrderedDict, you could use package json

>>> import json
>>> json.loads(json.dumps(a))

[{'a': 'b', 'c': 'd', 'e': {'a': 'b', 'c': 'd'}}]
Audio answered 7/6, 2019 at 12:28 Comment(1)
I tried your solution but I have something like this : {ValueError}dictionary update sequence element #0 has length x; y is requiredChangsha
O
1

You can build a recursive function to do the conversion from OrderedDict to dict, checking for the datatypes using isinstance calls along the way.

from collections import OrderedDict

def OrderedDict_to_dict(arg):
    if isinstance(arg, (tuple, list)): #for some iterables. might need modifications/additions?
        return [OrderedDict_to_dict(item) for item in arg]

    if isinstance(arg, OrderedDict): #what we are interested in
        arg = dict(arg)

    if isinstance(arg, dict): #next up, iterate through the dictionary for nested conversion
        for key, value in arg.items():
            arg[key] = OrderedDict_to_dict(value)

    return arg

a = [OrderedDict([('a','b'), ('c','d'), ('e', OrderedDict([('a','b'), ('c','d') ]))])]


result = OrderedDict_to_dict(a)
print(result)
#Output:
[{'a': 'b', 'c': 'd', 'e': {'a': 'b', 'c': 'd'}}]

However, note that OrderedDicts are dictionaries too, and support key lookups.

print(a[0]['e'])
#Output:
OrderedDict([('a', 'b'), ('c', 'd')])

a[0]['e']['c']
#Output:
'd'

So, you should not need to convert the OrderedDicts to dicts if you just need to access the values as a dictionary would allow, since OrderedDict supports the same operations.

Obituary answered 7/6, 2019 at 13:10 Comment(0)
S
0

To convert a nested OrderedDict, you could use For:

from collections import OrderedDict
a = [OrderedDict([('id', 8)]), OrderedDict([('id', 9)])]
data_list = []
for i in a:
    data_list.append(dict(i))
print(data_list)
#Output:[{'id': 8}, {'id': 9}]
Shillong answered 17/2, 2021 at 10:31 Comment(0)
C
0

You should leverage Python's builtin copy mechanism.

You can override copying behavior for OrderedDict via Python's copyreg module (also used by pickle). Then you can use Python's builtin copy.deepcopy() function to perform the conversion.

import copy
import copyreg
from collections import OrderedDict

def convert_nested_ordered_dict(x):
    """
    Perform a deep copy of the given object, but convert
    all internal OrderedDicts to plain dicts along the way.

    Args:
        x: Any pickleable object

    Returns:
        A copy of the input, in which all OrderedDicts contained
        anywhere in the input (as iterable items or attributes, etc.)
        have been converted to plain dicts.
    """
    # Temporarily install a custom pickling function
    # (used by deepcopy) to convert OrderedDict to dict.
    orig_pickler = copyreg.dispatch_table.get(OrderedDict, None)
    copyreg.pickle(
        OrderedDict,
        lambda d: (dict, ([*d.items()],))
    )
    try:
        return copy.deepcopy(x)
    finally:
        # Restore the original OrderedDict pickling function (if any)
        del copyreg.dispatch_table[OrderedDict]
        if orig_pickler:
            copyreg.dispatch_table[OrderedDict] = orig_pickler

Merely by using Python's builtin copying infrastructure, this solution is superior to all other answers presented here, in the following ways:

  • Works for more than just JSON data.

  • Does not require you to implement special logic for each possible element type (e.g. list, tuple, etc.)

  • deepcopy() will properly handle duplicate objects within the collection:

    x = [1,2,3]
    d = {'a': x, 'b': x}
    assert id(d['a']) == id(d['b'])
    
    d2 = copy.deepcopy(d)
    assert id(d2['a']) == id(d2['b'])
    

    Since our solution is based on deepcopy() we'll have the same advantage.

  • This solution also converts attributes that happen to be OrderedDict, not only collection elements:

    class C:
        def __init__(self, a=None, b=None):
            self.a = a or OrderedDict([(1, 'one'), (2, 'two')])
            self.b = b or OrderedDict([(3, 'three'), (4, 'four')])
    
        def __repr__(self):
            return f"C(a={self.a}, b={self.b})"
    
    
    print("original: ", C())
    print("converted:", convert_nested_ordered_dict(C()))
    
    original:  C(a=OrderedDict([(1, 'one'), (2, 'two')]), b=OrderedDict([(3, 'three'), (4, 'four')]))
    converted: C(a={1: 'one', 2: 'two'}, b={3: 'three', 4: 'four'})
    

Demonstration on your sample data:

a = [OrderedDict([('a','b'), ('c','d'), ('e', OrderedDict([('a','b'), ('c','d') ]))])]
b = convert_nested_ordered_dict(a)
print(b)
[{'a': 'b', 'c': 'd', 'e': {'a': 'b', 'c': 'd'}}]
Canny answered 3/8, 2022 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.