如何将一个列表分成 n 个等份,Python

15

对于任意的单词列表lst,我应该将其分成10个相等的部分。

x = len(lst)/10

如何为这些部分命名变量?

在输出中,我需要10个变量(part1、part2... part10),每个变量中都包含x个单词。


2
你没有给零件命名。你返回一个列表的列表。 - user395760
如何分割?[1,2,3,4,5,...100] 变成 [1,2,3,...],[11,12,13,...],... 或者 [1,11,21,...],[2,12,22,...],... 或者随机或其他方式? - kennytm
为什么不使用元组或另一个包含子列表的列表呢?然后通过位置引用它们?这样比使用变量更加动态。 <PRE> res = divide_list(l, 10) print res[0] </PRE> - khachik
markrian提醒我,这个问题不是重复的,所以我的答案是错误的。我正在标记为重新打开。这个问题是“如何将列表分成n个相等的部分”,而不是“如何将列表分成大小为n的块”。 - Paulo Scardine
9个回答

40

给定一个列表和分块大小,返回一个列表的列表的一行代码:

>>> lol = lambda lst, sz: [lst[i:i+sz] for i in range(0, len(lst), sz)]

测试:

>>> x = range(20, 36)
>>> print x
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]

>>> lol(x, 4)
[[20, 21, 22, 23], 
 [24, 25, 26, 27], 
 [28, 29, 30, 31], 
 [32, 33, 34, 35]]

>>> lol(x, 7)
[[20, 21, 22, 23, 24, 25, 26], 
 [27, 28, 29, 30, 31, 32, 33], 
 [34, 35]]

更新:

我认为这个问题实际上是在询问一个函数,它接受一个列表和一个数字,返回一个包含$(number)个列表的列表,其中原始列表的项目被平均分配到这些列表中。因此,你的lol(x, 7)的例子应该真正返回[[20,21,22],[23,24,25],[26,27],[28,29],[30,31],[32,33],[34,35]]。- markrian

在这种情况下,你可以尝试:

def slice_list(input, size):
    input_size = len(input)
    slice_size = input_size / size
    remain = input_size % size
    result = []
    iterator = iter(input)
    for i in range(size):
        result.append([])
        for j in range(slice_size):
            result[i].append(iterator.next())
        if remain:
            result[i].append(iterator.next())
            remain -= 1
    return result

我相信这可以改进,但懒得动手。 :-)

>>> slice_list(x, 7)
[[20, 21, 22], [23, 24, 25], 
 [26, 27], [28, 29], 
 [30, 31], [32, 33], 
 [34, 35]]

1
我认为这个问题实际上是在询问一个函数,该函数接受一个列表和一个数字作为参数,并返回一个包含$(number)个列表的列表,其中原始列表的项被均匀分配。 - markrian
哈哈,我写了一个与你的Python函数几乎完全相同的JS函数,一行一行地写,就在我写那个评论的时候 :) - markrian
很好。如果你只想循环一个范围而不操作生成的列表,使用xrange比range更好。 - ScotchAndSoda
是的,在您的情况下,lambda函数生成了一个列表作为结果,因此使用的范围被丢弃。 - ScotchAndSoda
请注意,由于range现在返回类似生成器的对象,因此只有在您使用非常旧的Python版本时,range与xrange之间的区别才是一个问题。 - Paulo Scardine
显示剩余3条评论

3
为了达到与Paulo更新相同的结果(将列表分成大小仅相差1的n个块),以下是使用递归的优雅解决方案。
def divide(lst, n):
    p = len(lst) // n
    if len(lst)-p > 0:
        return [lst[:p]] + divide(lst[p:], n-1)
    else:
        return [lst]

例子:

lst = list(range(13))
print divide(lst,5) # [[0, 1], [2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]

2
请查看这个问题来了解如何在Python中生成等分的列表。如果你真的需要将它们存储在不同的变量中,可以按照以下方式操作:
part1, part2, ..., part10 = (part for part in chunks(lst, len(lst)/10))

但我建议将代码更改为更通用的形式,而不是硬编码为10个部分。


生成器表达式是多余的。 - Azat Ibrakov

1

我会写这段代码让你学习技巧,但你不应该这样做。像 listset 这样的容器数据类型的重点是你可以拥有任意内容而不必为每个元素创建变量。所以,

不要这样做

>>> def chunks(l, n):
...     for i in xrange(0, len(l), n):
...         yield l[i:i+n]
...
>>> for i, chunk in enumerate(chunks(range(100), 10)):
...     locals()["part{0}".format(i)] = chunk
...
>>> part0
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> part1
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> part2
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]

chunks 配方来自于 Ned Batchelder's answer 的链接问题。你不应该这样做的原因是修改 locals(或者 globals 或者 vars)不是一个好的实践:它会导致难以确定的行为和可能非常严重的错误。)

1
如果 chunks 无法将列表 l 平均分成 n 份,那么它会将 l 分成 len(l)/n + 1 份(当 len(l)%n != 0 )或者 len(l)/n 份(当 len(l)%n == 0 )。 - khachik

1
如果您不需要强制连续的输出元素,则以下简单代码片段将完成工作:
def even_divide(lst, num_piece=4):
    return [
        [lst[i] for i in range(len(lst)) if (i % num_piece) == r]
        for r in range(num_piece)
    ]

基本上,代码根据模剩余值对元素进行分组。正因为如此,输出列表中的元素将不是连续的。例如,如果输入是range(21),输出将不会是连续的。
[[0, 1, 2, 3, 4, 5],[6, 7, 8, 9, 10],[11, 12, 13, 14, 15],[16, 17, 18, 19, 20]]

你会得到。
[[0, 4, 8, 12, 16, 20],[1, 5, 9, 13, 17],[2, 6, 10, 14, 18],[3, 7, 11, 15, 19]]

希望它有所帮助。

1
另一种选择。
chunk_size=5
_chunks=list(x [i:i+chunk_size]
                   for i in range(0, len(x ), chunk_size))

0

看到了几个解决方案,但还是想分享我的:

# List
lst = range(103)

# number of slices
nSlices = 10

# splitted list
slices = [len(lst) // (nSlices)] * nSlices

# but points are still missing!
remainder = len(lst)-sum(slices)

# split missing points across slices
slices[:remainder] = [ii + 1 for ii in slices[:remainder]]

splittedList = [lst[sum(slices[:ii]):sum(slices[:ii+1])] for ii in                range(nSlices)]
print lst
print '\n'.join("{}".format(n) for n in splittedList)

当然可以进一步概括,但我认为这样阅读起来更清晰。


0

与 @henneray 相同,针对数据框

def divide_df(df, n):    
    p = len(df.index) // n # size of one part is length / parts
    if len(df.index) - p > 0: # if a part of size p is still remaining
        return [df.iloc[0:p]] + divide(df.iloc[p:], n-1) # one part is from start to p, recursivly divide rest into n-1 pieces
    else:
        return [df]

0

使用元组/列表作为结果 - 最合理的方法

如果需要定义新变量,您可以:

  1. 使用 setattr 并向任何 object 添加新属性。这是安全的,因为您不会覆盖现有变量:
    res = object()
    ...
    setattr(res, "part"+index, part_generated)
    
  2. 根据代码运行的上下文将生成的变量添加到 locals()globals() 字典中。

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