Convert a grouping value to a list of scalar values :param grouping: grouping value to flatten :param schema: If provided, a grouping value representing the expected structure of the input grouping value. If not provided, the grouping value is its own schema. A schema i
(grouping, schema=None)
| 18 | |
| 19 | |
| 20 | def flatten_grouping(grouping, schema=None): |
| 21 | """ |
| 22 | Convert a grouping value to a list of scalar values |
| 23 | |
| 24 | :param grouping: grouping value to flatten |
| 25 | :param schema: If provided, a grouping value representing the expected structure of |
| 26 | the input grouping value. If not provided, the grouping value is its own schema. |
| 27 | A schema is required in order to be able treat tuples and dicts in the input |
| 28 | grouping as scalar values. |
| 29 | |
| 30 | :return: list of the scalar values in the input grouping |
| 31 | """ |
| 32 | stack = [] |
| 33 | result = [] |
| 34 | |
| 35 | # Avoid repeated recursive Python calls by using an explicit stack |
| 36 | push = stack.append |
| 37 | pop = stack.pop |
| 38 | |
| 39 | # Only validate once at the top if schema is provided |
| 40 | if schema is None: |
| 41 | schema = grouping |
| 42 | else: |
| 43 | validate_grouping(grouping, schema) |
| 44 | |
| 45 | push((grouping, schema)) |
| 46 | while stack: |
| 47 | group, sch = pop() |
| 48 | # Inline isinstance checks for perf |
| 49 | typ = type(sch) |
| 50 | if typ is tuple or typ is list: |
| 51 | # Avoid double recursion / excessive list construction |
| 52 | for ge, se in zip(group, sch): |
| 53 | push((ge, se)) |
| 54 | elif typ is dict: |
| 55 | for k in sch: |
| 56 | push((group[k], sch[k])) |
| 57 | else: |
| 58 | result.append(group) |
| 59 | result.reverse() # Since we LIFO, leaf values are in reverse order |
| 60 | return result |
| 61 | |
| 62 | |
| 63 | def grouping_len(grouping): |
searching dependent graphs…