如何将一个列表随机分成n个近乎相等的部分?

25

分区也是字符串的一种方法,所以您可能应该重新考虑命名。另外,我建议使用Mark Dickinson的无浮点第二个答案。 - Tony Veijalainen
6个回答

44

28

完整的2018年解决方案(Python 3.6):

import random 
def partition (list_in, n):
    random.shuffle(list_in)
    return [list_in[i::n] for i in range(n)]

注意!这可能会改变您原来的列表。


可能会发生变异 => 一定会发生变异,但解决这个问题就像复制原始列表一样容易。 - norok2

3

对输入列表进行随机排序。


1
那绝对有道理。我真的应该想到这一点。唉,一万小时定律可能是真的 :-( - Darren J. Fitzpatrick

2

首先,您需要将列表随机化,然后将其分成n个几乎相等的部分。


1

对列表进行洗牌并不保留顺序。你可以尝试使用以下方法(很容易适应于超过两个部分)。完全未经测试。

from __future__ import annotations
from typing import TypeVar
import random

T = TypeVar("T")

def partition_list(s: list[T]) -> tuple[list[T], list[T]]:
    """
    Randomly partition a list into two lists, preserving order. The number to
    take is drawn from a uniform distribution.
    """
    len_a = random.randint(0, len(s))
    len_b = len(s) - len_a
    put_in_a = [True] * len_a + [False] * len_b
    random.shuffle(put_in_a)
    a: list[T] = []
    b: list[T] = []

    for val, in_a in zip(s, put_in_a):
        if in_a:
            a.append(val)
        else:
            b.append(val)

    return a, b

0
随机分区同时保留顺序:
def partition_preserve_order(list_in, n):
    indices = list(range(len(list_in)))
    shuffle(indices)
    index_partitions = [sorted(indices[i::n]) for i in range(n)]
    return [[list_in[i] for i in index_partition] 
            for index_partition in index_partitions]

(也就是说,我们对索引进行洗牌,然后在分区内对它们进行排序)

示例:

random_partition_preserve_order(list('abcdefghijklmnopqrstuvxyz'), 3)
# [
#     ['c', 'd', 'g', 'm', 'p', 'r', 'v', 'x', 'y'], 
#     ['b', 'e', 'h', 'k', 'o', 'q', 't', 'u'], 
#     ['a', 'f', 'i', 'j', 'l', 'n', 's', 'z']
# ]

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