diff options
Diffstat (limited to 'parse/col_map.py')
-rw-r--r-- | parse/col_map.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/parse/col_map.py b/parse/col_map.py new file mode 100644 index 0000000..6f83ca1 --- /dev/null +++ b/parse/col_map.py | |||
@@ -0,0 +1,79 @@ | |||
1 | from collections import defaultdict | ||
2 | |||
3 | class ColMapBuilder(object): | ||
4 | def __init__(self): | ||
5 | self.value_map = defaultdict(set) | ||
6 | |||
7 | def build(self): | ||
8 | columns = sorted(self.value_map.keys(), | ||
9 | key=lambda c: (len(self.value_map[c]), c)) | ||
10 | col_list = filter(lambda c : len(self.value_map[c]) > 1, columns) | ||
11 | return ColMap(col_list) | ||
12 | |||
13 | def try_add(self, column, value): | ||
14 | self.value_map[column].add( value ) | ||
15 | |||
16 | def try_remove(self, column): | ||
17 | del(self.value_map[column]) | ||
18 | |||
19 | class ColMap(object): | ||
20 | def __init__(self, col_list): | ||
21 | self.col_list = col_list | ||
22 | self.rev_map = {} | ||
23 | |||
24 | for i, col in enumerate(col_list): | ||
25 | self.rev_map[col] = i | ||
26 | |||
27 | def columns(self): | ||
28 | return self.col_list | ||
29 | |||
30 | def get_key(self, kv): | ||
31 | '''Convert a key-value dict into an ordered tuple of values.''' | ||
32 | key = () | ||
33 | |||
34 | for col in self.col_list: | ||
35 | if col not in kv: | ||
36 | key += (None,) | ||
37 | else: | ||
38 | key += (kv[col],) | ||
39 | |||
40 | return key | ||
41 | |||
42 | def get_kv(self, key): | ||
43 | '''Convert an ordered tuple of values into a key-value dict.''' | ||
44 | kv = {} | ||
45 | for i in range(0, len(key)): | ||
46 | kv[self.col_list[i]] = key[i] | ||
47 | return kv | ||
48 | |||
49 | |||
50 | def encode(self, kv): | ||
51 | '''Converted a dict into a string with items sorted according to | ||
52 | the ColMap key order.''' | ||
53 | def escape(val): | ||
54 | return str(val).replace("_", "-").replace("=", "-") | ||
55 | |||
56 | vals = [] | ||
57 | |||
58 | for key in self.col_list: | ||
59 | if key not in kv: | ||
60 | continue | ||
61 | k, v = escape(key), escape(kv[key]) | ||
62 | vals += ["%s=%s" % (k, v)] | ||
63 | |||
64 | return "_".join(vals) | ||
65 | |||
66 | @staticmethod | ||
67 | def decode(string): | ||
68 | '''Convert a string into a key-value dict.''' | ||
69 | vals = {} | ||
70 | for assignment in string.split("_"): | ||
71 | k, v = assignment.split("=") | ||
72 | vals[k] = v | ||
73 | return vals | ||
74 | |||
75 | def __contains__(self, col): | ||
76 | return col in self.rev_map | ||
77 | |||
78 | def __str__(self): | ||
79 | return "<ColMap>%s" % (self.rev_map) | ||