jason
jason

Reputation: 2106

how to random generate a sequence of list that are unobserved before in python 3

Assume I have the code in Python 3

X, Y, Z = 10, 20, 30
data = [[1,3,6],[8,15,29],[8,9,19]] # observe data

Then how can I random generate n (not very large) data elements that are not in the data.

Condition: the element [a,b,c] must be not in data and 0<a<X, 0<b<Y, 0<c<Z

[1,3,5] is good since it is not in data and its element satisfy the Condition

[11,3,6] is bad since it does not satisfy the Condition, 11>10

For example, when n=4, I want a list of element that are not duplicate

newdata = [[1,6,6],[8,17,25],[2,6,11], [4,6,12]] 

Upvotes: 2

Views: 75

Answers (4)

This should do it:

from random import randint

X, Y, Z = 10, 20, 30
data = [[1,3,6],[8,15,29],[8,9,19]]
n = 4

newdata = set()

for i in range(n):
    while True:
    l = [randint(1, X), randint(1, Y), randint(1, Z)]
    if l not in data:
        newdata.add(tuple(l))
        break

print(newdata)

Example result:

newdata = [(9, 9, 11), (10, 10, 4), (7, 6, 23), (2, 10, 4)]

Upvotes: 1

a_guest
a_guest

Reputation: 36299

For higher performance you can use Numpy and the fact that the tuples can be converted to integer and back by simply enumerating them (as z, y, x gets enumerated):

import numpy as np

x, y, z = 100, 200, 300
n = 1000

data = [[1,3,6],[8,15,29],[8,9,19]]
forbidden = [i[0]*y*z + i[1]*z + i[2] for i in data]
pool = np.arange(x*y*z)
mask = np.ones(pool.size, dtype=bool)
mask[forbidden] = False
pool = pool[mask]
newdata = np.random.choice(pool, n, replace=False)
newdata = [(i // (y*z), i // z, i % z) for i in newdata]

Upvotes: 0

a_guest
a_guest

Reputation: 36299

In case X, Y, Z are not too large you can just create all possible combinations and then sample from this pool:

import itertools as it
import random

x, y, z = 10, 20, 30
pool = it.product(range(x), range(y), range(z))
data = [(1, 3, 6), (8, 15, 29), (8, 9, 19)]
pool = set(pool) - set(data)
n = 4
newdata = random.sample(pool, n)

Upvotes: 0

Bradley Hastings
Bradley Hastings

Reputation: 51

It took a small effort, but this seems to work:

from random import *
from pprint import pprint

X, Y, Z = 10, 20, 30
data = [[1,3,6],[8,15,29],[8,9,19]]

while 1:
    newData = []
    try: n = int(input("How many lists do you want: "))
    except:
        print("Please enter an integer.\n")
        continue
    for i in range(n):
        newList = [randrange(1, X), randrange(1, Y), randrange(1, Z)]
        while (newList in data) or (newList in newData):
            newList = [randrange(1, X), randrange(1, Y), randrange(1, Z)]
        newData.append(newList)
    pprint(newData)

This works by creating an empty list, getting a value for n, then entering a loop of exactly n iterations. It then creates a new list that satisfies the requirements. If the new list is in the observed data list, it just does it again and again until it isn't in the data. Then it adds this data to the output list and repeats the process until the for loop breaks (after n iterations).

There may be a better way of doing it, but this does the trick.

Upvotes: 0

Related Questions