Splitting a list into uneven groups?

前端 未结 6 1967
北海茫月
北海茫月 2020-12-14 20:47

I know how to split a list into even groups, but I\'m having trouble splitting it into uneven groups.

Essentially here is what I have: some list, let\'s call it

相关标签:
6条回答
  • 2020-12-14 20:56

    You can create an iterator and itertools.islice:

    mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    seclist = [2,4,6]
    
    from itertools import islice
    it = iter(mylist)
    
    sliced =[list(islice(it, 0, i)) for i in seclist]
    

    Which would give you:

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

    Once i elements are consumed they are gone so we keep getting the next i elements.

    Not sure what should happen with any remaining elements, if you want them added, you could add something like:

    mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ,14]
    seclist = [2, 4, 6]
    
    from itertools import islice
    
    it = iter(mylist)
    
    slices = [sli for sli in (list(islice(it, 0, i)) for i in seclist)]
    remaining = list(it)
    if remaining:
        slices.append(remaining)
    print(slices)
    

    Which would give you:

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

    Or in contrast if there were not enough, you could use a couple of approaches to remove empty lists, one an inner generator expression:

    from itertools import islice
    
    it = iter(mylist)
    slices = [sli for sli in (list(islice(it, 0, i)) for i in seclist) if sli]
    

    Or combine with itertools.takewhile:

     from itertools import islice, takewhile
    
    it = iter(mylist)
    slices = list(takewhile(bool, (list(islice(it, 0, i)) for i in seclist)))
    

    Which for:

    mylist = [1, 2, 3, 4, 5, 6]
    seclist = [2, 4, 6,8]
    

    would give you:

    [[1, 2], [3, 4, 5, 6]]
    

    As opposed to:

    [[1, 2], [3, 4, 5, 6], [], []]
    

    What you use completely depends on your possible inouts and how you would like to handle the various possibilities.

    0 讨论(0)
  • 2020-12-14 21:05

    This solution keeps track of how many items you've written. It will crash if the sum of the numbers in the second_list is longer than mylist

    total = 0
    listChunks = []
    for j in range(len(second_list)):
        chunk_mylist = mylist[total:total+second_list[j]]
        listChunks.append(chunk_mylist)
        total += second_list[j]
    

    After running this, listChunks is a list containing sublists with the lengths found in second_list.

    0 讨论(0)
  • 2020-12-14 21:10

    A numpythonic approach:

    >>> lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    >>> sec = [2, 4, 5]
    >>> np.split(lst, np.cumsum(sec))
    [array([0, 1]), array([2, 3, 4, 5]), array([ 6,  7,  8,  9, 10]), array([11])]
    

    And here is a Python3.X approach using itertool.accumulate():

    >>> lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    >>> sec = [2,4,6]
    >>> from itertools import accumulate
    >>> sec = list(accumulate(sec_lst))
    >>> sec = [0] + sec + [None] if sec[0] != 0 else sec + [None]
    >>> 
    >>> [lst[i:j] for i, j in zip(sec, sec[1:])]
    [[0, 1], [2, 3, 4, 5], [6, 7, 8, 9, 10], [11]]
    
    0 讨论(0)
  • 2020-12-14 21:15

    Using list-comprehensions together with slicing and sum() function (all basic and built-in tools of python):

    mylist = [1,2,3,4,5,6,7,8,9,10]
    seclist = [2,4,6]
    
    [mylist[sum(seclist[:i]):sum(seclist[:i+1])] for i in range(len(seclist))]
    
    #output:
    [[1, 2], [3, 4, 5, 6], [7, 8, 9, 10]]
    

    If seclist is very long and you wish to be more efficient use numpy.cumsum() first:

    import numpy as np
    cumlist = np.hstack((0, np.cumsum(seclist)))
    [mylist[cumlist[i]:cumlist[i+1]] for i in range(len(cumlist)-1)]
    

    and get the same results

    0 讨论(0)
  • 2020-12-14 21:20

    Padriac has the best solution IMO, but I'll chime in with this hacky one liner that requires no imports:

    >>> L = [1,2,3,4,5,6,7,8,9,10] # source list - could be any iterable
    >>> S = [2,3,4] # group sizes - could be any iterable
    
    >>> [ [ [ next(i) for k in range(j) ] for j in iter(S) ] for i in [iter(L)] ][0]
    [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
    
    0 讨论(0)
  • 2020-12-14 21:21
    subgroups = []
    start=0
    for i in second_list:
      subgroups.append(mylist[start:start + i])
      start = i + start
    

    At the end subgroups will contain the desired lists

    Example run:

    >>> mylist = [1,2,3,4,5,6,7,8,9,10,11,12]
    >>> second_list = [2,4,5,9]
    >>> subgroups = []
    >>> start=0
    >>> for i in second_list:
    ...    subgroups.append(mylist[start:start + i])
    ...    start = i + start
    ...
    >>> subgroups
    [[1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11], [12]]
    
    0 讨论(0)
提交回复
热议问题