随机将列表分成两个或三个项目的块

3
我卡在了一个涉及将列表分成不同大小块的问题上。我想要一个列表,随机分成2个或3个一组。
例如:
L = [1,1,1,1,1,1,1,1,1,1,1,1]

我想表达的意思是:“我想说出一些话。”
L2 = [(1,1,1),(1,1),(1,1),(1,1,1),(1,1)]

但是我希望这是随机的,这样每次运行代码时成对和三元组的分布都会改变。

5
可能是将列表随机分割成大小不等的块的最佳方法?的重复。 - Billal Begueradj
那里的答案非常优雅。但是对于这种特定情况,它们有时会导致一个包含1个元素的块,而列表可以仅分成2和3的倍数。例如:在使用min_chunk=2maxchunk=3运行时,接受的答案在其中一个迭代中为L2给出了[[1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1]] - Vasanth
5个回答

2
作为一种更通用的方法,您可以使用以下函数:
from itertools import count
import random
def my_split(lst, chunks):
    def chunk_creator():
        total = 0
        while total <= len(lst):
            x = random.choice(chunks)
            yield L[total: x + total]
            total += x
        yield total - x

    def chunk_finder():
        for _ in count():
            chunk = list(chunk_creator())
            total = chunk.pop(-1)
            if total == len(L):
                return chunk[:-1]
    if max(chunks) <= len(L):
        return chunk_finder()
    else:
        return None

演示:

>>> L = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 
>>> my_split(L, (2, 3))
... [[1, 1], [1, 1], [1, 1], [1, 1, 1], [1, 1, 1]]
>>> my_split(L, (2, 3))
... [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]]

说明:

此函数由两个子函数组成。第一个是chunk_creator,它的作用是根据列表长度创建所需的块,并将它们返回为迭代器。请注意,结束值是“total”变量,它是前面块的总和。

第二个函数(chunk_finder)将通过无限循环(itertools.count())并检查输入列表的长度是否等于total的值来找到我们需要的块。


1

有很多方法可以解决这个问题,也许你可以编写一个生成器,根据 size 函数返回不同大小的块:

import random

def take_chunked(i, size):
    idx = 0
    while idx < len(i):
        s = size(i[idx:])
        yield i[idx:idx+s]
        idx += s

def size_fun(i):
    if len(i) == 4:
        return 2
    if len(i) <= 3:
        return len(i)

    return random.randint(2,3)

输出:

>>> list(take_chunked("helloworld", size_fun))
['he', 'll', 'owo', 'rld']
>>> list(take_chunked("helloworld", size_fun))
['hel', 'low', 'or', 'ld']
>>> list(take_chunked("a", size_fun))
['a']
>>> list(take_chunked("", size_fun))
[]

这个版本将保证块的大小为2或3,只要列表中有足够的项目。


是的,我添加了关于那个的注释。 - André Laszlo
修复了这个问题,使用一个不那么优雅的 size_fun 进行更新。 - André Laszlo

0
len(L)分解为2和3的块,然后使用循环来分割列表。
import numpy as np

def rand23():
    return np.random.randint(2,4)

def get_chunk(sz):
    rem = sz
    ch = []
    while ( rem > 0 ):
        if ( rem <= 3 ): #if <= 3 add what is left in the chunk (exit condition)
            ch.append(rem)
            rem = 0
            break
        elif ( rem == 4 ): #4 is the only edge case here
            ch.append(2)
            ch.append(2)
            rem = 0
            break
        else:
            ch.append(rand23())
            rem -= ch[-1]

    return ch

L = [1,1,1,1,1,1,1,1,1,1,1,1]
ch = get_chunk(len(L))
L2 = []
count = 0
#Divide the list into chunks based on ch
for c in ch:
    L2.append(tuple(L[count:count+c]))
    count += c

print L2

结果:(每行是迭代的输出)

[(1, 1, 1), (1, 1), (1, 1), (1, 1), (1, 1, 1)]

[(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1)]

[(1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1)]

[(1, 1), (1, 1), (1, 1, 1), (1, 1, 1), (1, 1)]

[(1, 1, 1), (1, 1), (1, 1), (1, 1), (1, 1, 1)]

[(1, 1, 1), (1, 1, 1), (1, 1), (1, 1), (1, 1)]

[(1, 1), (1, 1), (1, 1, 1), (1, 1), (1, 1, 1)]

PS:你也可以递归地实现get_chunk()


这将始终给出相同的结果。OP要求一系列随机的对和三元组。 - jusx
对啊,稍微晚了点才意识到。我正在纠正答案。 - Vasanth

0
希望这能帮到你。
步骤1:使用随机模块生成一个随机数。
步骤2:使用随机数来决定它应该是一对还是2(如果随机数是偶数)/3(如果随机数不是偶数)。
步骤3:编写代码。
from random import random

def selector():
    s = int(random() * 100 )
    return (s/2) == 0

L = [1 for i in range(30)]
L2 = []

while L:
    if selector():
        tmp = 2
    else:
        tmp = 3
    #print tmp
    if tmp > 0 and len(L) >= tmp:
        L2.append( [ L.pop() for i in range(tmp)] )
    if len(L) < 3:
        L2.append(set(L))
        L = []

print L, L2

0

这个很简单,可以解决问题 :-)

import random

L = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
L2 = list()

i = 0
j = random.randint(2, 3)

while i < len(L):
    chunk = L[i:j]
    L2.append(chunk)
    i = j
    if len(L) - i == 4:  # case: 4 elements left in L
        j = i + 2
    elif len(L) - i < 4:  # case: 2 or 3 elements left in L
        j = len(L)
    else:
        j = i + random.randint(2, 3)

print L
print L2

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