How to elegantly interleave two lists of uneven length in python?

前端 未结 8 1434
自闭症患者
自闭症患者 2021-01-04 06:13

I want to merge two lists in python, with the lists being of different lengths, so that the elements of the shorter list are as equally spaced within the final list as possi

8条回答
  •  旧巷少年郎
    2021-01-04 07:00

    I like unutbu's answer but not the nested style, so I rewrote it. While I was there I noticed the sorting wasn't stable, so I fixed it using operator.itemgetter.

    I also replaced itertools.count with enumerate because it's more intuitive. As a bonus it should also be more accurate for large inputs, though I haven't tested it.

    import itertools
    import operator
    
    def distribute(sequence):
        """
        Enumerate the sequence evenly over the interval (0, 1).
    
        >>> list(distribute('abc'))
        [(0.25, 'a'), (0.5, 'b'), (0.75, 'c')]
        """
        m = len(sequence) + 1
        for i, x in enumerate(sequence, 1):
            yield i/m, x
    
    def intersperse(*sequences):
        """
        Evenly intersperse the sequences.
    
        Based on https://stackoverflow.com/a/19293603/4518341
    
        >>> list(intersperse(range(10), 'abc'))
        [0, 1, 'a', 2, 3, 4, 'b', 5, 6, 7, 'c', 8, 9]
        >>> list(intersperse('XY', range(10), 'abc'))
        [0, 1, 'a', 2, 'X', 3, 4, 'b', 5, 6, 'Y', 7, 'c', 8, 9]
        >>> ''.join(intersperse('hlwl', 'eood', 'l r!'))
        'hello world!'
        """
        distributions = map(distribute, sequences)
        get0 = operator.itemgetter(0)
        for _, x in sorted(itertools.chain(*distributions), key=get0):
            yield x
    

    Note that there's one difference from your second example, where 'b' and 'c' get moved down:

    >>> list(intersperse(range(1, 6), 'abc'))
    [1, 'a', 2, 3, 'b', 4, 'c', 5]
    

提交回复
热议问题