user6534794
user6534794

Reputation:

I want to randomly select items from a list and add them to another list without replacement

I'm trying to randomly select items from a list and add them to another list.

The list of elements I'm choosing from looks like this:

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

I want to randomly take an element from this list and add it to one of four lists until each list has the same number of elements.

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']]

I have tried using random.choice but this gives me duplicates:

def fill_lists(data):
for list in lists:
    for n,i in enumerate(list):
        if i=='x':
            list[n]= random.choice(data)

I want my function to return a list that contains 4 lists each containing a random sample of the data list with no duplicates. I also want the first element of each list to be a value that I have already placed into the list.

Upvotes: 3

Views: 3127

Answers (5)

Ted Klein Bergman
Ted Klein Bergman

Reputation: 9746

This is a dynamic function that returns a list of list where each list starts with a specified value. The amount of nested lists is determined by the amount of 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]]

It works for Python2.x and Python3.x but for Python2.x you should change range() to xrange() for better use of memory.

Upvotes: 0

dashiell
dashiell

Reputation: 812

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)

Randomly pulling from your initial list will have the same effect as shuffling then pulling in order. Splitting into sublists can then be done. If you need the sublists sorted, just map sort over the list afterwards.

You can change the number of groups by altering the divisor of len(data)/4

Edit: I missed this part of your question:

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

Upvotes: 3

zenofsahil
zenofsahil

Reputation: 1753

You could try this, modifying the ranges inside the d function to tune to the number elements you want.

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)

This will always give you 4 lists of randomly sampled values without duplication.

Upvotes: 0

karakfa
karakfa

Reputation: 67497

another shuffle based but ensuring the all sub lists have the same size in case number of elements is not divisible to number of lists (try 7 for example).

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))

Upvotes: 0

Peter Wang
Peter Wang

Reputation: 1838

You can use 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]

To get a nested list of it, use a list comprehension

 [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]]

Edit: The above won't give you unique values; you should accept the above answer for the unique values. I interpreted the question wrong!

Upvotes: 1

Related Questions