|
14 | 14 | 'first', 'second', 'nth', 'last', 'get', 'concat', 'concatv', |
15 | 15 | 'mapcat', 'cons', 'interpose', 'frequencies', 'reduceby', 'iterate', |
16 | 16 | 'sliding_window', 'partition', 'partition_all', 'count', 'pluck', |
17 | | - 'join', 'tail', 'diff', 'topk', 'peek', 'random_sample') |
| 17 | + 'join', 'tail', 'diff', 'topk', 'peek', 'random_sample', |
| 18 | + 'dichotomize') |
18 | 19 |
|
19 | 20 |
|
20 | 21 | def remove(predicate, seq): |
@@ -980,3 +981,48 @@ def random_sample(prob, seq, random_state=None): |
980 | 981 | if not hasattr(random_state, 'random'): |
981 | 982 | random_state = Random(random_state) |
982 | 983 | return filter(lambda _: random_state.random() < prob, seq) |
| 984 | + |
| 985 | + |
| 986 | +def _complement_iterator(it, predicate, our_queue, other_queue): |
| 987 | + for element in our_queue: |
| 988 | + yield element |
| 989 | + our_queue.clear() |
| 990 | + |
| 991 | + for element in it: |
| 992 | + if predicate(element): |
| 993 | + yield element |
| 994 | + else: |
| 995 | + other_queue.append(element) |
| 996 | + |
| 997 | + for element in our_queue: |
| 998 | + yield element |
| 999 | + our_queue.clear() |
| 1000 | + |
| 1001 | + |
| 1002 | +def dichotomize(predicate, iterable): |
| 1003 | + """Take a predicate and an iterable and return the pair of iterables of |
| 1004 | + elements which do and do not satisfy the predicate. The resulting iterators |
| 1005 | + are lazy. |
| 1006 | +
|
| 1007 | + >>> def even(n): |
| 1008 | + ... return n & 1 == 0 |
| 1009 | + ... |
| 1010 | + >>> evens, odds = dichotomize(even, range(10)) |
| 1011 | + >>> list(evens) |
| 1012 | + [0, 2, 4, 6, 8] |
| 1013 | + >>> list(odds) |
| 1014 | + [1, 3, 5, 7, 9] |
| 1015 | + """ |
| 1016 | + true_queue = collections.deque() |
| 1017 | + false_queue = collections.deque() |
| 1018 | + it = iter(iterable) |
| 1019 | + |
| 1020 | + return ( |
| 1021 | + _complement_iterator(it, predicate, true_queue, false_queue), |
| 1022 | + _complement_iterator( |
| 1023 | + it, |
| 1024 | + lambda element: not predicate(element), |
| 1025 | + false_queue, |
| 1026 | + true_queue, |
| 1027 | + ), |
| 1028 | + ) |
0 commit comments