Skip to content

Instantly share code, notes, and snippets.

@AdotDdot
Last active August 29, 2015 14:05
Show Gist options
  • Select an option

  • Save AdotDdot/74f509d0c0d9b40d2b4d to your computer and use it in GitHub Desktop.

Select an option

Save AdotDdot/74f509d0c0d9b40d2b4d to your computer and use it in GitHub Desktop.

Revisions

  1. AdotDdot revised this gist Aug 16, 2014. 1 changed file with 2 additions and 5 deletions.
    7 changes: 2 additions & 5 deletions caselessOrderedDict.py
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@
    class COD(dict):
    '''Caseless Ordered Dictionary
    Enables case insensitive searching and updating while preserving case sensitivity when keys are listed.
    Combination of the code of collections.OrderedDict and CaselessDictionary (https://gist.github.com/babakness/3901174) '''
    Combination of the code of collections.OrderedDict and CaselessDictionary (https://gist.github.com/bloomonkey/3003096) '''

    def __init__(self, *args, **kwds):
    '''Initialize an ordered dictionary. The signature is the same as
    @@ -111,10 +111,7 @@ def get(self, key, default=None):
    return v['val']

    def has_key(self,key):
    if self.get(key):
    return True
    else:
    return False
    return key in self

    update = MutableMapping.update

  2. AdotDdot created this gist Aug 16, 2014.
    220 changes: 220 additions & 0 deletions caselessOrderedDict.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,220 @@
    from _abcoll import *
    from operator import eq as _eq
    from itertools import imap as _imap
    try:
    from thread import get_ident as _get_ident
    except ImportError:
    from dummy_thread import get_ident as _get_ident

    class COD(dict):
    '''Caseless Ordered Dictionary
    Enables case insensitive searching and updating while preserving case sensitivity when keys are listed.
    Combination of the code of collections.OrderedDict and CaselessDictionary (https://gist.github.com/babakness/3901174) '''

    def __init__(self, *args, **kwds):
    '''Initialize an ordered dictionary. The signature is the same as
    regular dictionaries, but keyword arguments are not recommended because
    their insertion order is arbitrary.
    '''
    if len(args) > 1:
    raise TypeError('expected at most 1 arguments, got %d' % len(args))
    try:
    self.__root
    except AttributeError:
    self.__root = root = [] # sentinel node
    root[:] = [root, root, None]
    self.__map = {}
    self.__update(*args, **kwds)

    def __contains__(self, key):
    return dict.__contains__(self, key.lower())

    def __getitem__(self, key):
    return dict.__getitem__(self, key.lower())['val']

    def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
    if key not in self:
    root = self.__root
    last = root[0]
    last[1] = root[0] = self.__map[key] = [last, root, key]
    return dict.__setitem__(self, key.lower(), {'key': key, 'val': value})

    def __delitem__(self, key, dict_delitem=dict.__delitem__):
    'od.__delitem__(y) <==> del od[y]'
    # Deleting an existing item uses self.__map to find the link which gets
    # removed by updating the links in the predecessor and successor nodes.
    dict_delitem(self, key)
    link_prev, link_next, _ = self.__map.pop(key)
    link_prev[1] = link_next # update link_prev[NEXT]
    link_next[0] = link_prev # update link_next[PREV]

    def __iter__(self):
    'od.__iter__() <==> iter(od)'
    # Traverse the linked list in order.
    root = self.__root
    curr = root[1] # start at the first node
    while curr is not root:
    yield curr[2] # yield the curr[KEY]
    curr = curr[1] # move to next node

    def __reversed__(self):
    'od.__reversed__() <==> reversed(od)'
    # Traverse the linked list in reverse order.
    root = self.__root
    curr = root[0] # start at the last node
    while curr is not root:
    yield curr[2] # yield the curr[KEY]
    curr = curr[0] # move to previous node

    def clear(self):
    'od.clear() -> None. Remove all items from od.'
    root = self.__root
    root[:] = [root, root, None]
    self.__map.clear()
    dict.clear(self)

    # -- the following methods do not depend on the internal structure --

    def keys(self):
    'od.keys() -> list of keys in od'
    return list(self)

    def values(self):
    'od.values() -> list of values in od'
    return [self[key] for key in self]

    def items(self):
    'od.items() -> list of (key, value) pairs in od'
    return [(key, self[key]) for key in self]

    def iterkeys(self):
    'od.iterkeys() -> an iterator over the keys in od'
    return iter(self)

    def itervalues(self):
    'od.itervalues -> an iterator over the values in od'
    for k in self:
    yield self[k]

    def iteritems(self):
    'od.iteritems -> an iterator over the (key, value) pairs in od'
    for k in self:
    yield (k, self[k])

    def get(self, key, default=None):
    try:
    v = dict.__getitem__(self, key.lower())
    except KeyError:
    return default
    else:
    return v['val']

    def has_key(self,key):
    if self.get(key):
    return True
    else:
    return False

    update = MutableMapping.update

    __update = update # let subclasses override update without breaking __init__

    __marker = object()

    def pop(self, key, default=__marker):
    '''od.pop(k[,d]) -> v, remove specified key and return the corresponding
    value. If key is not found, d is returned if given, otherwise KeyError
    is raised.
    '''
    if key in self:
    result = self[key]
    del self[key]
    return result
    if default is self.__marker:
    raise KeyError(key)
    return default

    def setdefault(self, key, default=None):
    'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
    if key in self:
    return self[key]
    self[key] = default
    return default

    def popitem(self, last=True):
    '''od.popitem() -> (k, v), return and remove a (key, value) pair.
    Pairs are returned in LIFO order if last is true or FIFO order if false.
    '''
    if not self:
    raise KeyError('dictionary is empty')
    key = next(reversed(self) if last else iter(self))
    value = self.pop(key)
    return key, value

    def __repr__(self, _repr_running={}):
    'od.__repr__() <==> repr(od)'
    call_key = id(self), _get_ident()
    if call_key in _repr_running:
    return '...'
    _repr_running[call_key] = 1
    try:
    if not self:
    return '%s()' % (self.__class__.__name__,)
    return '%s(%r)' % (self.__class__.__name__, self.items())
    finally:
    del _repr_running[call_key]

    def __reduce__(self):
    'Return state information for pickling'
    items = [[k, self[k]] for k in self]
    inst_dict = vars(self).copy()
    for k in vars(OrderedDict()):
    inst_dict.pop(k, None)
    if inst_dict:
    return (self.__class__, (items,), inst_dict)
    return self.__class__, (items,)

    def copy(self):
    'od.copy() -> a shallow copy of od'
    return self.__class__(self)

    @classmethod
    def fromkeys(cls, iterable, value=None):
    '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
    If not specified, the value defaults to None.
    '''
    self = cls()
    for key in iterable:
    self[key] = value
    return self

    def __eq__(self, other):
    '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
    while comparison to a regular mapping is order-insensitive.
    '''
    if isinstance(other, OrderedDict):
    return dict.__eq__(self, other) and all(_imap(_eq, self, other))
    return dict.__eq__(self, other)

    def __ne__(self, other):
    'od.__ne__(y) <==> od!=y'
    return not self == other

    # -- the following methods support python 3.x style dictionary views --

    def viewkeys(self):
    "od.viewkeys() -> a set-like object providing a view on od's keys"
    return KeysView(self)

    def viewvalues(self):
    "od.viewvalues() -> an object providing a view on od's values"
    return ValuesView(self)

    def viewitems(self):
    "od.viewitems() -> a set-like object providing a view on od's items"
    return ItemsView(self)