Splitting a list into N parts of approximately equal length

前端 未结 30 1301
迷失自我
迷失自我 2020-11-22 16:16

What is the best way to divide a list into roughly equal parts? For example, if the list has 7 elements and is split it into 2 parts, we want to get 3 elements in o

相关标签:
30条回答
  • 2020-11-22 16:55

    Here is my solution:

    def chunks(l, amount):
        if amount < 1:
            raise ValueError('amount must be positive integer')
        chunk_len = len(l) // amount
        leap_parts = len(l) % amount
        remainder = amount // 2  # make it symmetrical
        i = 0
        while i < len(l):
            remainder += leap_parts
            end_index = i + chunk_len
            if remainder >= amount:
                remainder -= amount
                end_index += 1
            yield l[i:end_index]
            i = end_index
    

    Produces

        >>> list(chunks([1, 2, 3, 4, 5, 6, 7], 3))
        [[1, 2], [3, 4, 5], [6, 7]]
    
    0 讨论(0)
  • 2020-11-22 16:55

    Here's another variant that spreads the "remaining" elements evenly among all the chunks, one at a time until there are none left. In this implementation, the larger chunks occur at the beginning the process.

    def chunks(l, k):
      """ Yield k successive chunks from l."""
      if k < 1:
        yield []
        raise StopIteration
      n = len(l)
      avg = n/k
      remainders = n % k
      start, end = 0, avg
      while start < n:
        if remainders > 0:
          end = end + 1
          remainders = remainders - 1
        yield l[start:end]
        start, end = end, end+avg
    

    For example, generate 4 chunks from a list of 14 elements:

    >>> list(chunks(range(14), 4))
    [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10], [11, 12, 13]]
    >>> map(len, list(chunks(range(14), 4)))
    [4, 4, 3, 3]
    
    0 讨论(0)
  • 2020-11-22 16:56

    Have a look at numpy.split:

    >>> a = numpy.array([1,2,3,4])
    >>> numpy.split(a, 2)
    [array([1, 2]), array([3, 4])]
    
    0 讨论(0)
  • 2020-11-22 16:57

    Rounding the linspace and using it as an index is an easier solution than what amit12690 proposes.

    function chunks=chunkit(array,num)
    
    index = round(linspace(0,size(array,2),num+1));
    
    chunks = cell(1,num);
    
    for x = 1:num
    chunks{x} = array(:,index(x)+1:index(x+1));
    end
    end
    
    0 讨论(0)
  • 2020-11-22 16:57

    say you want to split into 5 parts:

    p1, p2, p3, p4, p5 = np.split(df, 5)
    
    0 讨论(0)
  • 2020-11-22 16:58

    This code is broken due to rounding errors. Do not use it!!!

    assert len(chunkIt([1,2,3], 10)) == 10  # fails
    

    Here's one that could work:

    def chunkIt(seq, num):
        avg = len(seq) / float(num)
        out = []
        last = 0.0
    
        while last < len(seq):
            out.append(seq[int(last):int(last + avg)])
            last += avg
    
        return out
    

    Testing:

    >>> chunkIt(range(10), 3)
    [[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
    >>> chunkIt(range(11), 3)
    [[0, 1, 2], [3, 4, 5, 6], [7, 8, 9, 10]]
    >>> chunkIt(range(12), 3)
    [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
    
    0 讨论(0)
提交回复
热议问题