Completed
Push — master ( 64da81...89f930 )
by Chris
01:28
created

group_by()   F

Complexity

Conditions 9

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
c 1
b 0
f 0
dl 0
loc 39
rs 3
1
"""Filters for working with data structures, munging, etc..."""
2
3
from collections import defaultdict
4
5
6
def filter_list(lst, vals):
7
    """Filter a list by vals.
8
9
    Args:
10
        lst (dict): The dictionary to filter.
11
12
    Returns:
13
        string (dict): The filtered dict.
14
    """
15
    if any([not lst, not isinstance(lst, list), not isinstance(vals, list)]):
16
        return lst
17
    return list(set(lst).difference(set(vals)))
18
19
20
def filter_vals(obj, vals):
21
    """Filter a dictionary by values.
22
23
    Args:
24
        obj (dict): The dictionary to filter.
25
26
    Returns:
27
        obj (dict): The filtered dict.
28
    """
29
    if obj is None or not isinstance(vals, list):
30
        return obj
31
    newdict = {}
32
    for k, v in obj.items():
33
        if v in vals:
34
            continue
35
        newdict[k] = v
36
    return newdict
37
38
39
def filter_keys(obj, keys):
40
    """Filter a dictionary by keys.
41
42
    Args:
43
        obj (dict): The dictionary to filter.
44
45
    Returns:
46
        obj (dict): The filtered dict.
47
    """
48
    if obj is None or not isinstance(keys, list):
49
        return obj
50
    newdict = {}
51
    for k, v in obj.items():
52
        if k in keys:
53
            continue
54
        newdict[k] = v
55
    return newdict
56
57
58
def group_by(objs, groups={}, attr='name'):
59
    """Group a list of objects into a dict grouped by specified keys.
60
61
    Args:
62
        objs: A list of objects
63
        keys: A dict of keys and their corresponding names to match on.
64
        attr: The attr to use to get fields for matching (default: {'name'})
65
66
    Returns:
67
        A grouped dictionary and objects.
68
        dict
69
70
    >>> group_by(
71
        [obj1, obj2], groups={'name1': 'g1', 'name2': 'g1'}, attr='name')
72
    """
73
    grouped = defaultdict(list)
74
    seen = []
75
    group_matches = groups.keys()
76
77
    for obj in objs:
78
        # Get the attribute by a specified attr (e.g. `foo.name`)
79
        obj_label = None
80
        if attr is not None and hasattr(obj, attr):
81
            obj_label = getattr(obj, attr)
82
        # Don't add more than once...
83
        if obj_label is not None and obj_label in seen:
84
            continue
85
        seen.append(obj_label)
86
        # If it matches the current attr,
87
        # put it in the corresponding group.
88
        if obj_label in group_matches:
89
            for label, group in groups.items():
90
                if obj_label == label:
91
                    grouped[group].append(obj)
92
        else:
93
            # Ensure all fields are present even if they weren't grouped
94
            # by the user. Using a special key to group all others by.
95
            grouped['__unlabeled'].append(obj)
96
    return grouped
97