How Can This Function Be Rewritten to Implement Ordereddict

How can this function be rewritten to implement OrderedDict?

You could use the new OrderedDictdict subclass which was added to the standard library's collections module in version 2.7. Actually what you need is an Ordered+defaultdict combination which doesn't exist — but it's possible to create one by subclassing OrderedDict as illustrated below:

If your version of Python doesn't have OrderedDict, you should be able use Raymond Hettinger's Ordered Dictionary for Py2.4 ActiveState recipe as the base class instead.

import collections

class OrderedDefaultdict(collections.OrderedDict):
""" A defaultdict with OrderedDict as its base class. """

def __init__(self, default_factory=None, *args, **kwargs):
if not (default_factory is None or callable(default_factory)):
raise TypeError('first argument must be callable or None')
super(OrderedDefaultdict, self).__init__(*args, **kwargs)
self.default_factory = default_factory # called by __missing__()

def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key,)
self[key] = value = self.default_factory()
return value

def __reduce__(self): # Optional, for pickle support.
args = (self.default_factory,) if self.default_factory else tuple()
return self.__class__, args, None, None, iter(self.items())

def __repr__(self): # Optional.
return '%s(%r, %r)' % (self.__class__.__name__, self.default_factory, self.items())

def simplexml_load_file(file):
from lxml import etree

tree = etree.parse(file)
root = tree.getroot()

def xml_to_item(el):
item = el.text or None
child_dicts = OrderedDefaultdict(list)
for child in el.getchildren():
child_dicts[child.tag].append(xml_to_item(child))
return collections.OrderedDict(child_dicts) or item

def xml_to_dict(el):
return {el.tag: xml_to_item(el)}

return xml_to_dict(root)

x = simplexml_load_file('routines/test.xml')
print(x)

for y in x['root']:
print(y)

The output produced from your test XML file looks like this:

{'root':
OrderedDict(
[('a', ['1']),
('aa', [OrderedDict([('b', [OrderedDict([('c', ['2'])]), '2'])])]),
('aaa', ['3']),
('aaaa', [OrderedDict([('bb', ['4'])])]),
('aaaaa', ['5'])
]
)
}

a
aa
aaa
aaaa
aaaaa

Which I think is close to what you want.

Minor update:

Added a __reduce__() method which will allow the instances of the class to be pickled and unpickled properly. This wasn't necessary for this question, but came up in a similar one.

How to implement an ordered, default dict?

The following (using a modified version of this recipe) works for me:

from collections import OrderedDict, Callable

class DefaultOrderedDict(OrderedDict):
# Source: http://stackoverflow.com/a/6190500/562769
def __init__(self, default_factory=None, *a, **kw):
if (default_factory is not None and
not isinstance(default_factory, Callable)):
raise TypeError('first argument must be callable')
OrderedDict.__init__(self, *a, **kw)
self.default_factory = default_factory

def __getitem__(self, key):
try:
return OrderedDict.__getitem__(self, key)
except KeyError:
return self.__missing__(key)

def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = value = self.default_factory()
return value

def __reduce__(self):
if self.default_factory is None:
args = tuple()
else:
args = self.default_factory,
return type(self), args, None, None, self.items()

def copy(self):
return self.__copy__()

def __copy__(self):
return type(self)(self.default_factory, self)

def __deepcopy__(self, memo):
import copy
return type(self)(self.default_factory,
copy.deepcopy(self.items()))

def __repr__(self):
return 'OrderedDefaultDict(%s, %s)' % (self.default_factory,
OrderedDict.__repr__(self))

Ordered Dictionary in Python

The moment you write dict = {'a':1, 'q':1, 'l':2, 'm':1, 'u':1, 'i':1}, you already have lost the order of the elements. The ways to keep it:

a. Create OrderedDict from your data in the first place.

b. Convert your dict to a list of tuples and sort in a way you want, then create OrderedDict from it.

All in all, from your question it is not clear what you want to preserve. If it is generated "randomly" then who cares, if there is some logic behind it, then use this logic to recreate that order and create OrderedDict using it. If there is something happening behind the scenes which creates this dict from some input data, then, alas, the order in which you see it is not the order in which it has been created.

PS And don't call your dict dict.

Use of Ordered Dict

Since python 3.7 Dictionary order is guaranteed to be insertion order.
check this answer for similar question link

subclassing from OrderedDict and defaultdict

Inheriting from OrderedDict as in the answer you linked to is the simplest way. It is more work to implement an ordered store than it is to get default values from a factory function.

All you need to implement for defaultdict is a bit of custom __init__ logic and the extremely simple __missing__.

If you instead inherit from defaultdict, you have to delegate to or re-implement at least __setitem__, __delitem__ and __iter__ to reproduce the in-order operation. You still have to do setup work in __init__, though you might be able to inherit or simply leave out some of the other methods depending on your needs.

Take a look at the original recipe or any of the others linked to from another Stack Overflow question for what that would entail.

OrderedDict Isn't Ordered?

collections.OrderedDict keeps track of the order in which elements were added to it. This would work fine in a loop:

c = collections.OrderedDict()
for a,b in zip('abc', (1,2,3)):
c[a] = b

However, the expression OrderedDict(a=1,b=2,c=3) creates an OrderedDict by passing several keyword arguments to its constructor. In Python 2.7, the order of keyword arguments is not guaranteed. If you want that, you'll have to move to Python 3.6, which implements PEP 468, Preserving the order of **kwargs in a function.

The **kwargs syntax in a function definition indicates that the interpreter should collect all keyword arguments that do not correspond to other named parameters. However, Python does not preserved the order in which those collected keyword arguments were passed to the function. In some contexts the order matters. This PEP dictates that the collected keyword arguments be exposed in the function body as an ordered mapping.

How do you retrieve items from a dictionary in the order that they're inserted?

The standard Python dict does this by default if you're using CPython 3.6+ (or Python 3.7+ for any other implementation of Python).

On older versions of Python you can use collections.OrderedDict.



Related Topics



Leave a reply



Submit