SHOW:
|
|
- or go back to the newest paste.
| 1 | # Refer to examples in ReversibleDict.__str__ | |
| 2 | ||
| 3 | class PrintableList(list): | |
| 4 | ||
| 5 | def __init__(self, list_, separator=', ', separate_last=False): | |
| 6 | self.separator = separator | |
| 7 | self.separate_last = separate_last | |
| 8 | list.__init__(self, list_) | |
| 9 | ||
| 10 | def __str__(self): | |
| 11 | """ | |
| 12 | Return a valid English string representation. | |
| 13 | ||
| 14 | Example: | |
| 15 | >>> for i in range(5): print(i, PrintableList(range(i))) | |
| 16 | ... | |
| 17 | (0, []) | |
| 18 | (1, [0]) | |
| 19 | (2, [0, 1]) | |
| 20 | (3, [0, 1, 2]) | |
| 21 | (4, [0, 1, 2, 3]) | |
| 22 | """ | |
| 23 | ||
| 24 | separator = self.separator | |
| 25 | separator_last = separator if self.separate_last else ' ' | |
| 26 | separator_last = '{0}and '.format(separator_last)
| |
| 27 | ||
| 28 | s = (str(i) for i in self) | |
| 29 | s = separator.join(s) | |
| 30 | s = separator_last.join(s.rsplit(separator, 1)) | |
| 31 | ||
| 32 | return s | |
| 33 | ||
| 34 | ||
| 35 | class ReversibleDict(dict): | |
| 36 | ||
| 37 | def reversed(self, sort_values=True): | |
| 38 | """ | |
| 39 | Return a reversed dict, with common values in the original dict | |
| 40 | grouped into a list in the returned dict. | |
| 41 | ||
| 42 | Example: | |
| 43 | >>> d = ReversibleDict({'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2})
| |
| 44 | >>> d.reversed() | |
| 45 | {1: ['d'], 2: ['b', 'c', 'f'], 3: ['a', 'e']}
| |
| 46 | """ | |
| 47 | ||
| 48 | revdict = {}
| |
| 49 | for k, v in self.iteritems(): | |
| 50 | revdict.setdefault(v, []).append(k) | |
| 51 | if sort_values: | |
| 52 | revdict = dict((k, sorted(v)) for k, v in revdict.items()) | |
| 53 | return revdict | |
| 54 | ||
| 55 | def _reversed_tuple_revlensorted(self): | |
| 56 | """ | |
| 57 | Return a tuple created from the reversed dict's items (see the | |
| 58 | `reversed` method), with the items in the tuple being reverse sorted by | |
| 59 | the length of the reversed dict's values. | |
| 60 | ||
| 61 | Example: | |
| 62 | >>> d = ReversibleDict({'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2})
| |
| 63 | >>> d._reversed_tuple_revlensorted() | |
| 64 | ((2, ['b', 'c', 'f']), (3, ['a', 'e']), (1, ['d'])) | |
| 65 | """ | |
| 66 | ||
| 67 | revitems = self.reversed().items() | |
| 68 | sortkey = lambda i: (len(i[1]), i[0]) | |
| 69 | revtuple = tuple(sorted(revitems, key=sortkey, reverse=True)) | |
| 70 | return revtuple | |
| 71 | ||
| 72 | def __str__(self): | |
| 73 | """ | |
| 74 | Return a string representation of the reversed dict's items (see the | |
| 75 | `reversed` method), sorted per the `_reversed_tuple_revlensorted` | |
| 76 | method. | |
| 77 | ||
| 78 | Example | |
| 79 | >>> print(ReversibleDict({'a':3, 'c':2, 'b':2, 'e':3, 'd':1, 'f':2}))
| |
| 80 | b, c and f (2); a and e (3); and d (1) | |
| 81 | >>> print(ReversibleDict({'a': 3, 'c': 2}))
| |
| 82 | a (3) and c (2) | |
| 83 | """ | |
| 84 | revtuple = self._reversed_tuple_revlensorted() | |
| 85 | ||
| 86 | revstrs = ('{0} ({1})'.format(PrintableList(values), key)
| |
| 87 | for key, values in revtuple) | |
| 88 | pl_args = ('; ', True) if (max(len(i[1]) for i in revtuple) > 1) else ()
| |
| 89 | revstrs = PrintableList(revstrs, *pl_args) | |
| 90 | revstr = str(revstrs) | |
| 91 | return revstr |