Skip to content

Instantly share code, notes, and snippets.

@aramk
Created October 17, 2011 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aramk/1292554 to your computer and use it in GitHub Desktop.
Save aramk/1292554 to your computer and use it in GitHub Desktop.
Python Ordered Dictinary
# -*- coding: utf-8 -*-
'''
Ordered dict
http://ak.net84.net/projects/python-ordered-dictionary/
Example usage:
>>> o = Ordict( ('abc', 123), ('def', '456', 3) )
>>> o['ghi'] = '789'
>>> o['jkl'] = 987
>>> o['mno'] = '654' # replaces index 3
>>> o.set('pqr', 321, 5)
>>> print o
Ordict {0: ['abc', 123], 1: ['ghi', '789'], 2: ['jkl', 987], 3: ['mno', '654'], 5: ['pqr', 321]}
>>> print o.item_at(2)
['jkl', 987]
'''
class Ordict(dict):
def __init__(self, *args, **kwargs):
self.ordered_items = {} # {0:('a':'b'), 4:('c','d')...}
self.item_to_order = {} # {'a':0, 'c':4}
self.next_index = 0 # The next available index
for item in args:
if len(item) > 3:
raise Exception('Ordered items must be tuples: (key , value [, index])')
elif len(item) == 2:
self.__setitem__(item[0], item[1])
elif len(item) == 3:
if item[2] < 0:
raise Exception('Index must be given as a positive integer')
self.__setitem__(item[0], item[1], item[2])
return dict.__init__(self, **kwargs)
def __getitem__(self, key):
return dict.__getitem__(self, str(key))
def __setitem__(self, key, value, index=None):
key = str(key)
_index = self.next_index
if type(index) is int:
_index = abs(index)
# Find next available index. If current next_index is untaken, keep it.
# If this set took it, increment
if _index == self.next_index:
self.next_index += 1
else:
self.next_index += 1 # increment index
self.ordered_items[_index] = [key, value]
self.item_to_order[key] = _index
dict.__setitem__(self, key, value)
def __delitem__(self, key):
key = str(key)
index = self.item_to_order[key]
del self.ordered_items[index]
return dict.__delitem__(self, key)
def __iter__(self):
for index in self.ordered_items:
item = self.ordered_items[index]
yield item[0]
def __repr__(self):
return 'Ordict ' + self.ordered_items.__repr__()
def set(self, key, value, index=None):
'''
Set the key:value with optional index
'''
return self.__setitem__(key, value, index)
def index_of(self, key, default=None):
'''
Return index of key or 'default' if it doesn't exist
'''
key = str(key)
return self.item_to_order[key] if key in self.item_to_order else default
def item_at(self, index, default=None):
'''
Return item at index as a tuple or 'default' if it doesn't exist
'''
index = int(index)
item = self.ordered_items[index] if index in self.ordered_items else None
if item:
return item
else:
return default
def key_at(self, index, default=None):
'''
Return key at index or 'default' if it doesn't exist
'''
index = int(index)
item = self.item_at(index)
if item:
return item[0]
else:
return default
def value_at(self, index, default=None):
'''
Return value at index or 'default' if it doesn't exist
'''
index = int(index)
item = self.item_at(index)
if item:
return item[1]
else:
return default
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment