从一个列表中随机选择项目并将其添加到另一个列表,且不重复。

3

我正在尝试从一个列表中随机选择项目并将它们添加到另一个列表中。

我要选择的元素列表看起来像这样:

data=[2,3,4,7,8,12,17,24,27,33,35,36,37,38,40,43,44,50,51,54]

我希望能够从这个列表中随机取出一个元素,并将其添加到四个列表中的一个,直到每个列表具有相同数量的元素。
lists=[[1,'x','x','x','x','x'],[3,'x','x','x','x','x'],[5,'x','x','x','x','x'],[7,'x','x','x','x','x']]

我尝试过使用random.choice,但这会给我重复的结果:
def fill_lists(data):
for list in lists:
    for n,i in enumerate(list):
        if i=='x':
            list[n]= random.choice(data)

我希望我的函数返回一个包含4个列表的列表,每个列表都包含数据列表的随机样本且没有重复项。 我还希望每个列表的第一个元素是我已经放入列表中的值。


先对数据进行随机化/洗牌,然后开始填充列表。 - Eitan K
1
你正在混淆数据并将其分割。不确定如何在Python中实现,但我相信有一个split(sample(data), rep(1:4, 5))的翻译。 - Pierre L
5个回答

3
import random
data=[2,3,4,7,8,12,17,24,27,33,35,36,37,38,40,43,44,50,51,54]
random.shuffle(data)
lists = [data[i:i+len(data)/4] for i in range(0, len(data), len(data)/4)]
print(lists)

随机从初始列表中选择与洗牌后按顺序选择具有相同效果。然后可以将其拆分为子列表。如果需要对子列表进行排序,只需在列表后映射排序即可。

您可以通过改变 len(data)/4 的除数来更改组数。

编辑:我错过了您问题的这一部分:

heads = [1,3,5,7]
[q.insert(0,p) for p,q in zip(heads,lists)]

我正在将值放入一个新列表中。我假设旧列表可以被丢弃,但如果不是这种情况,那么他或她在洗牌之前可以复制数据。 - dashiell
好的,我只是想匹配OP的命名方式,以便与示例给出相同的结果。 - Checkmate
@dashiell 这是Python2.x还是Python3.x?这段代码在Python3.x中无法运行,但你的打印方式表明了Python3.x。 - Ted Klein Bergman
我想确保在编辑列表时,我可以将列表的第一个元素保留为预选值。 - user6534794
在这种情况下,你应该使用 ´xrange()´ 而不是 ´range()´,对吧 @dashiell? - Ted Klein Bergman
显示剩余2条评论

1
你可以使用 random.sample:
 data=[2,3,4,7,8,12,17,24,27,33,35,36,37,38,40,43,44,50,51,54]
 random.sample(data, 5)
 # [27, 12, 33, 24, 17]

要获取一个嵌套列表,可以使用列表推导式

 [random.sample(data, 5) for _ in range(5)]
 # [[40, 35, 24, 54, 17],
 #  [17, 54, 35, 43, 37],
 #  [40, 4, 43, 33, 44],
 #  [51, 37, 35, 33, 8],
 #  [54, 4, 44, 27, 50]]

编辑:以上代码无法给出唯一值;对于唯一值,您应该接受上面的答案。我误解了问题!


0
你可以尝试这个方法,修改 d 函数内的范围以调整所需元素的数量。
import random

def f(data):
    val = random.choice(data)
    ix = data.index(val)
    data.pop(ix)
    return val, data

def d(data):
    topholder = []
    m = len(data)/4
    for i in range(4):
        holder = []
        for n in range(m):
            holder.append(f(data)[0])
        topholder.append(holder)
    return topholder

d(data)

这将始终为您提供4个随机抽样值列表,且不重复。


0

另一种基于洗牌的方法,但确保所有子列表的大小相同,以防元素数量不能被列表数整除(例如尝试7)。

from random import shuffle

def split(data, n):   
    size=int(len(data)/n);
    for i in range(0, n*size, size):
        yield data[i:i+size]


data=[2,3,4,7,8,12,17,24,27,33,35,36,37,38,40,43,44,50,51,54]
shuffle(data)
list(split(data, 5))

0
这是一个动态函数,它返回一个列表的列表,其中每个列表都以指定的值开头。嵌套列表的数量由“starting_values”的数量确定。
import random

def get_random_list(element_list, starting_values, size_per_group):
    num_of_groups = len(starting_values)
    size_per_group -= 1
    total_elements = num_of_groups * size_per_group
    random_data = random.sample(element_list, total_elements)
    return [[starting_values[x]] + random_data[x * size_per_group:(x + 1) * size_per_group] for x in range(num_of_groups)]

data = [2, 3, 4, 7, 8, 12, 17, 24, 27, 33, 35, 36, 37, 38, 40, 43, 44, 50, 51, 54]

print(get_random_list(data, starting_values=[1, 2, 3, 4, 5, 6], size_per_group=2))
# OUTPUT: [[1, 36], [2, 54], [3, 17], [4, 7], [5, 35], [6, 33]]
print(get_random_list(data, starting_values=[9, 3, 5], size_per_group=6))
# OUTPUT: [[9, 54, 2, 7, 38, 24], [3, 35, 8, 37, 40, 17], [5, 44, 4, 27, 50, 3]]

它适用于Python2.x和Python3.x,但对于Python2.x,您应该将range()更改为xrange()以更好地利用内存。


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