将一个列表分成n个子列表,余数添加到最后一个子列表中。

3

我昨晚问过这个问题,但我表达得不好。

我正在尝试处理一个列表:

['milk','eggs','beef','oranges','dog food','chips','soda','bread']

将其分成每个列表包含 n 个项目,任何余数需要均匀地加到列表中... 因此当 n = 3 时,结果应该是:
[['milk','eggs','beef'],['oranges','dog food','chips']]

如果剩下的是:['soda','bread'],那么最终结果将是:

[['milk','eggs','beef','soda'],['oranges','dog food','chips','bread']]

顺序无关紧要。


如果你有十个元素,而n=3,你会怎么做?余数只有一个元素长,所以不能均匀地添加到所有的列表中。 - undefined
然后将其添加到任何列表中会很好。 - undefined
Matthew,你的帖子似乎缺少一个问题。你有什么具体问题我们可以为你解答吗? - undefined
如何编写一个函数,能够接收类似上述的列表,并将它们拆分返回,这应该是最佳的方法? - undefined
7个回答

5
一种简短而高效的解决方案:
def splitList (lst, n):
    it = iter(lst)
    new = [[next(it) for _ in range(n)] for _ in range(len(lst) // n)]

    for i, x in enumerate(it):
        new[i].append(x)

    return new

>>> lst = ['milk', 'eggs', 'beef', 'oranges', 'dog food', 'chips', 'soda', 'bread']
>>> splitList(lst, 3)
[['milk', 'eggs', 'beef', 'soda'], ['oranges', 'dog food', 'chips', 'bread']]
>>> splitList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3)
[[1, 2, 3, 10], [4, 5, 6], [7, 8, 9]]

首先我们创建一个迭代器,这个迭代器可以用于所有操作;因此我们只需要对列表进行一次循环。将会创建的子列表数量为len(lst) // n(整数除法向下取整),对于每个子列表,我们从迭代器中获取n个值。

之后,剩余的项目仍然留在迭代器中,因此我们可以直接迭代它们并将它们附加到子列表中。


这对于某些以n为分割的情况不起作用。在一个361个项目的列表中,如果按照超过约50的任何值进行分割,将会超出索引范围。 - undefined

1
我相信下面的代码非常简单,而且能够很好地为您服务。请注意,它需要more_itertools模块。
from more_itertools import chunked

x = ['milk','eggs','beef','oranges','dog food','chips','soda','bread']

def foo(lst,num):
    chunk = list(chunked(lst,num))

    if len(chunk[-1]) == num:
        return chunk

    for i,val in enumerate(chunk[-1]):
        chunk[i].append(val)
    del chunk[-1]

    return chunk

ans = foo(x,3)
# [['milk', 'eggs', 'beef', 'soda'], ['oranges', 'dog food', 'chips', 'bread']]

代码使用more_itertools的chunked方法将列表按大小为n(在您的示例中为3)分成子列表,任何余数都在最后一个子列表中。然后我迭代这个最终子列表并将其元素附加到您现有的子列表中。最后的子列表然后被删除。

y是从哪里来的? - undefined
抱歉,我将变量名从y改为chunk,忘记了最后一个,现在已经编辑好了。 - undefined

1

对于一个列表a,你可以通过floor(len(a) / n)来获得最小长度为n的组数。

def split(a, minSize):
    numGroups = int(len(a) / minSize)
    return [a[i::numGroups] for i in range(numGroups)]

@poke 我以为他说"顺序不重要"。 - undefined
哦!我没看到,对不起! - undefined

0
我试着回答了你的问题。对于列表中剩余部分的添加,我还有一些不太清楚的地方,所以可能需要在某个时候进行修订。 请告诉我下面的函数是否符合你的需求。
groceryList = ['milk', 'eggs', 'beef', 'oranges', 'dog food', 'chips', 'soda', 'bread']
outlist = []
listLength = len(groceryList)
modulus = listLength // 3
remainder = listLength % 3
print listLength, modulus, remainder
ending = 0
while modulus >= 1:
    outlist.append(groceryList[ending:ending+3])
    ending += 3
    modulus -= 1

print "value of ending", ending
outlistcounter = 0
if remainder > 0:
    while remainder != 0:
        outlist[outlistcounter].extend(groceryList[ending:ending+1])
        outlistcounter += 1
        remainder -= 1
        ending += 1
print outlist

0

试试这个:

def split_list(lst, n):
    result = []
    # split off elements in groups of `n`
    i = 0
    while i+n <= len(lst):
        result.append([])
        for k in range(n):
            result[-1].append(lst[i+k])
        i += n
    # add the remainder to the groups
    j = 0
    while i < len(lst):
        result[j].append(lst[i])
        i += 1
        j += 1
        j %= len(result)
    return result

lst = ['milk','eggs','beef','oranges','dog food','chips','soda','bread']
for i in range(1, len(lst)):
    print(i, split_list(lst, i))

结果:
1 [['milk'], ['eggs'], ['beef'], ['oranges'], ['dog food'], ['chips'], ['soda'], ['bread']]
2 [['milk', 'eggs'], ['beef', 'oranges'], ['dog food', 'chips'], ['soda', 'bread']]
3 [['milk', 'eggs', 'beef', 'soda'], ['oranges', 'dog food', 'chips', 'bread']]
4 [['milk', 'eggs', 'beef', 'oranges'], ['dog food', 'chips', 'soda', 'bread']]
5 [['milk', 'eggs', 'beef', 'oranges', 'dog food', 'chips', 'soda', 'bread']]
6 [['milk', 'eggs', 'beef', 'oranges', 'dog food', 'chips', 'soda', 'bread']]
7 [['milk', 'eggs', 'beef', 'oranges', 'dog food', 'chips', 'soda', 'bread']]

这样做有点奇怪,我想你可能从错误的角度来解决问题。

0
这对于你所要求的似乎是有效的:
def f(x, n):

    if n > len(x):
        return

    y = [x[i: i + n] for i in range(0, len(x), n)]  #split the list up into lists by n

    if len(y[-1]) != n:  #if there is a remainder
        remainder = y[-1]   
        y = y[:-1]

        count = 0
        while remainder:  #while remainder is not an empty list
            for lst in y:
                lst.append(remainder.pop())  #pop the remaining items into each of the other lists 
                count += 1
    return y

示例输出:

myList =['milk','eggs','beef','oranges','dog food','chips','soda','bread']

print f(myList, 3)

[['milk', 'eggs', 'beef', 'bread'], ['oranges', 'dog food', 'chips', 'soda']]

0

就像上面的可能稍微短一点

def Matts_list( l, n ):
    return_list = [ l[i:i + n] for i in range( 0, len( l ), n ) ]
    # last list isn't n long
    if len( return_list[-1] ) != n :
        last = return_list.pop()
        for i in range( 0, len( last ) ):
            return_list[i % len( return_list )].append( last[i] )
    return return_list

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接