Iteration over list slices

后端 未结 9 532
名媛妹妹
名媛妹妹 2020-11-30 00:59

I want an algorithm to iterate over list slices. Slices size is set outside the function and can differ.

In my mind it is something like:

for list_of_x         


        
9条回答
  •  有刺的猬
    2020-11-30 01:38

    If you want to divide a list into slices you can use this trick:

    list_of_slices = zip(*(iter(the_list),) * slice_size)
    

    For example

    >>> zip(*(iter(range(10)),) * 3)
    [(0, 1, 2), (3, 4, 5), (6, 7, 8)]
    

    If the number of items is not dividable by the slice size and you want to pad the list with None you can do this:

    >>> map(None, *(iter(range(10)),) * 3)
    [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]
    

    It is a dirty little trick


    OK, I'll explain how it works. It'll be tricky to explain but I'll try my best.

    First a little background:

    In Python you can multiply a list by a number like this:

    [1, 2, 3] * 3 -> [1, 2, 3, 1, 2, 3, 1, 2, 3]
    ([1, 2, 3],) * 3 -> ([1, 2, 3], [1, 2, 3], [1, 2, 3])
    

    And an iterator object can be consumed once like this:

    >>> l=iter([1, 2, 3])
    >>> l.next()
    1
    >>> l.next()
    2
    >>> l.next()
    3
    

    The zip function returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables. For example:

    zip([1, 2, 3], [20, 30, 40]) -> [(1, 20), (2, 30), (3, 40)]
    zip(*[(1, 20), (2, 30), (3, 40)]) -> [[1, 2, 3], [20, 30, 40]]
    

    The * in front of zip used to unpack arguments. You can find more details here. So

    zip(*[(1, 20), (2, 30), (3, 40)])
    

    is actually equivalent to

    zip((1, 20), (2, 30), (3, 40))
    

    but works with a variable number of arguments

    Now back to the trick:

    list_of_slices = zip(*(iter(the_list),) * slice_size)
    

    iter(the_list) -> convert the list into an iterator

    (iter(the_list),) * N -> will generate an N reference to the_list iterator.

    zip(*(iter(the_list),) * N) -> will feed those list of iterators into zip. Which in turn will group them into N sized tuples. But since all N items are in fact references to the same iterator iter(the_list) the result will be repeated calls to next() on the original iterator

    I hope that explains it. I advice you to go with an easier to understand solution. I was only tempted to mention this trick because I like it.

提交回复
热议问题