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 |