pythoniterable

How can one combine iterables keeping only the first element with each index?


Let's say I have a number of iterables:

[[1, 2], [3, 4, 5, 6], [7, 8, 9], [10, 11, 12, 13, 14]]

How can I get only each element that is the first to appear at its index in any of the iterables? In this case:

[1, 2, 5, 6, 14]

Visualized:

[1, 2]
[_, _, 5, 6]
[_, _, _]
[_, _, _, _, 14]

Solution

  • can it done in more functional style?

    Sure, but I wouldn't. Davis Herring's approach is already lovely. Here's a "more functional" way, but more obscure to my eyes:

    from itertools import zip_longest
    SKIP = object()
    
    def chain_suffixes(*iters):
        return (next(a for a in s if a is not SKIP)
                for s in zip_longest(*iters, fillvalue=SKIP))
    
    print(list(chain_suffixes(
          [1, 2], [3, 4, 5, 6], [7, 8, 9], [10, 11, 12, 13, 14])))
    

    which prints

    [1, 2, 5, 6, 14]

    EDIT

    BTW, "more functional" may be in the eye of the beholder. To my eyes, various forms of generator comprehension are just as "functional" as other ways of spelling it. At an extreme, it's possible to rewrite the above without using comprehensions at all, or even typing "def".

    from itertools import zip_longest
    
    SKIP = object()
    not_SKIP = lambda x: x is not SKIP
    first_not_SKIP = lambda s: next(filter(not_SKIP, s))
    chain_suffixes = lambda *iters: map(
        first_not_SKIP,
        zip_longest(*iters, fillvalue=SKIP))