Source code for chicken_turtle_util.multi_dict

# Copyright (C) 2016 VIB/BEG/UGent - Tim Diels <timdiels.m@gmail.com>
# 
# This file is part of Chicken Turtle Util.
# 
# Chicken Turtle Util is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# Chicken Turtle Util is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public License
# along with Chicken Turtle Util.  If not, see <http://www.gnu.org/licenses/>.

'''
multi-dict utilities. Multi-dicts can map keys to multiple values.

A multi-dict (or multi map) is a dict that maps each key to one or more values.
'''

from collections import defaultdict

[docs]class MultiDict(object): ''' A multi-dict view of a ``{hashable => {hashable}}`` dict. A light wrapper offering a few methods for working with multi-dicts. Parameters ---------- dict_ : {hashable => {hashable}} Dict to access as a multi-dict Notes ----- A multi-dict (or multi map) is a dict that maps each key to one or more values. ``MultiDict``\ s provided by other libraries tend to be more feature rich, while this interface is far more conservative. Instead of wrapping, they provide an interface that mixes regular and multi-dict access. Additionally, other ``MultiDict``\ 's map keys to lists of values, allowing a key to map to the same value multiple times. ''' def __init__(self, dict_): self._dict = dict_ @property def dict(self): ''' Get the underlying dict Returns ------- {hashable => {hashable}} ''' return self._dict def invert(self): ''' Invert by swapping each value with its key. Parameters ---------- dict_ : {hashable => {hashable}} Multi-dict to invert Returns ------- {hashable => {hashable}} `dict_` copy with key and value swapped. Examples -------- >>> invert({1: {1}, 2: {1,2,3}}, 4: {}) {1: {1,2}, 2: {2}, 3: {2}} ''' result = defaultdict(set) for k, val in self.items(): result[val].add(k) return dict(result) def items(self): return ((k, val) for k, vals in self._dict.items() for val in vals) def keys(self): return (k for k, vals in self._dict.items() if vals) def values(self): return (val for vals in self._dict.values() for val in vals)