Python: split a list based on a condition?

前端 未结 30 1841
误落风尘
误落风尘 2020-11-22 06:56

What\'s the best way, both aesthetically and from a performance perspective, to split a list of items into multiple lists based on a conditional? The equivalent of:

30条回答
  •  无人及你
    2020-11-22 07:05

    Inspired by @gnibbler's great (but terse!) answer, we can apply that approach to map to multiple partitions:

    from collections import defaultdict
    
    def splitter(l, mapper):
        """Split an iterable into multiple partitions generated by a callable mapper."""
    
        results = defaultdict(list)
    
        for x in l:
            results[mapper(x)] += [x]
    
        return results
    

    Then splitter can then be used as follows:

    >>> l = [1, 2, 3, 4, 2, 3, 4, 5, 6, 4, 3, 2, 3]
    >>> split = splitter(l, lambda x: x % 2 == 0)  # partition l into odds and evens
    >>> split.items()
    >>> [(False, [1, 3, 3, 5, 3, 3]), (True, [2, 4, 2, 4, 6, 4, 2])]
    

    This works for more than two partitions with a more complicated mapping (and on iterators, too):

    >>> import math
    >>> l = xrange(1, 23)
    >>> split = splitter(l, lambda x: int(math.log10(x) * 5))
    >>> split.items()
    [(0, [1]),
     (1, [2]),
     (2, [3]),
     (3, [4, 5, 6]),
     (4, [7, 8, 9]),
     (5, [10, 11, 12, 13, 14, 15]),
     (6, [16, 17, 18, 19, 20, 21, 22])]
    

    Or using a dictionary to map:

    >>> map = {'A': 1, 'X': 2, 'B': 3, 'Y': 1, 'C': 2, 'Z': 3}
    >>> l = ['A', 'B', 'C', 'C', 'X', 'Y', 'Z', 'A', 'Z']
    >>> split = splitter(l, map.get)
    >>> split.items()
    (1, ['A', 'Y', 'A']), (2, ['C', 'C', 'X']), (3, ['B', 'Z', 'Z'])]
    

提交回复
热议问题