3

I have a list of numbers such as

[5000, 5000, 5000, 5000, 5000, 5000]

I need to create a function that turns that list into a list of randomly sized smaller lists, such as :

[[5000, 5000], [5000, 5000, 5000], [5000]]

What's the best way to do this in python?

Talha Tayyab
  • 8,111
  • 25
  • 27
  • 44
Barry
  • 91
  • 3
  • 6
  • 6
    Do you want a fixed number of sublists? Can they be empty? What's the maximum length of a sublist? – RemcoGerlich Jan 29 '14 at 18:05
  • Sorry I didn't include that information in the original post. Not enough sleep is my excuse haha. Yes, a fixed number, they can't be empty and maximum length should be set in the arguments – Barry Jan 29 '14 at 21:50
  • The top answer actually works fine for my purposes. Thanks everyone for your suggestions. – Barry Jan 29 '14 at 21:58

7 Answers7

17
from itertools import islice
from random import randint

def random_chunk(li, min_chunk=1, max_chunk=3):
    it = iter(li)
    while True:
        nxt = list(islice(it,randint(min_chunk,max_chunk)))
        if nxt:
            yield nxt
        else:
            break

demo:

li = [5000, 5000, 5000, 5000, 5000, 5000]

list(random_chunk(li))
Out[45]: [[5000, 5000, 5000], [5000], [5000, 5000]]

This results in a (ignoring the last chunk) uniform distribution of chunk sizes between min_chunk and max_chunk, inclusively.

roippi
  • 25,533
  • 4
  • 48
  • 73
2

This is my approach to it: All resultant lists will have at least one element, but it may return a list with all numbers.

import random

def randomSublists(someList):
    resultList = [] #result container
    index = 0 #start at the start of the list
    length = len(someList) #and cache the length for performance on large lists
    while (index < length):
        randomNumber = random.randint(1, length-index+1) #get a number between 1 and the remaining choices
        resultList.append(someList[index:index+randomNumber]) #append a list starting at index with randomNumber length to it
        index = index + randomNumber #increment index by amount of list used
    return resultList #return the list of randomized sublists

Testing on the Python console:

>>> randomSublist([1,2,3,4,5])
[[1], [2, 3, 4, 5]]
>>> randomSublist([1,2,3,4,5])
[[1], [2, 3], [4], [5]]
>>> randomSublist([1,2,3,4,5])
[[1, 2, 3, 4, 5]]
>>> randomSublist([1,2,3,4,5])
[[1, 2], [3], [4, 5]]
>>> randomSublist([1,2,3,4,5])
[[1, 2, 3, 4, 5]]
>>> randomSublist([1,2,3,4,5])
[[1, 2, 3, 4], [5]]
>>> randomSublist([1,2,3,4,5])
[[1], [2, 3, 4], [5]]
>>> randomSublist([1,2,3,4,5])
[[1], [2, 3], [4], [5]]
>>> randomSublist([1,2,3,4,5])
[[1], [2], [3, 4, 5]]
>>> randomSublist([1,2,3,4,5])
[[1, 2, 3, 4, 5]]
>>> randomSublist([1,2,3,4,5])
[[1, 2, 3], [4, 5]]
>>> randomSublist([1,2,3,4,5])
[[1, 2, 3, 4], [5]]
1

Heres my attempt:

from random import randint

def random_list_split(data):
    split_list = []
    L = len(data)
    i = 0
    while i < L:
        r = randint(1,L-i)
        split_list.append(data[i:i+r])
        i = i + r
    return split_list

Some output data:

>>> random_list_split(test)
[[5000, 5000, 5000, 5000, 5000, 5000], [5000], [5000], [5000]]
>>> random_list_split(test)
[[5000, 5000, 5000, 5000], [5000, 5000], [5000, 5000], [5000]]
>>> random_list_split(test)
[[5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000], [5000]]
>>> random_list_split(test)
[[5000, 5000], [5000, 5000, 5000, 5000], [5000], [5000], [5000]]
>>> random_list_split(test)
[[5000, 5000, 5000, 5000, 5000, 5000], [5000], [5000], [5000]]
>>> random_list_split(test)
[[5000, 5000, 5000, 5000, 5000, 5000], [5000], [5000], [5000]]
>>> random_list_split(test)
[[5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000]]
Farmer Joe
  • 6,020
  • 1
  • 30
  • 40
1

You can simply iterate through the list (X) and with fixed probability (p) put element in the "last" sublist and with 1-p to the new one

import random

sublists = []
current = []
for x in X:
    if len(current)>0 and random.random() >= p:
        sublists.append(current)
        current = []
    current.append(x)
sublists.append(current)
lejlot
  • 64,777
  • 8
  • 131
  • 164
1

Here's one method:

def randsplit(lst):
    out = [[]]
    for item in lst:
        out[-1].append(item)
        if random.choice((True, False)):
            out.append([])
    return [l for l in out if len(l)]

This method neither mutates lst nor returns any empty lists. A sample:

>>> l =  [5000, 5000, 5000, 5000, 5000, 5000]
>>> randsplit(l) 
[[5000, 5000], [5000, 5000], [5000, 5000]]
>>> randsplit(l) 
[[5000, 5000, 5000], [5000, 5000], [5000]]
>>> randsplit(l) 
[[5000], [5000], [5000, 5000], [5000], [5000]]
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
0
import random

old_list = [5000, 5000, 5000, 5000, 5000, 5000]
new_list = []
def random_list(old, new):
    temp = []
    for each_item in old:
        temp.append(each_item)
        chance = random.randint(0,1)
        if chance < 1:
            new.append(temp)
            temp = []
    return new

a few outputs:

[[5000, 5000, 5000, 5000], [5000, 5000]]
[[5000, 5000, 5000, 5000], [5000], [5000]]
[[5000], [5000], [5000, 5000], [5000, 5000]]
kylieCatt
  • 10,672
  • 5
  • 43
  • 51
0

Small variation on roippi's answer:

In [1]: import itertools

In [2]: import random

In [3]: def random_chunk(li, min_chunk=1, max_chunk=3):
   ...:     it = iter(li)
   ...:     return list(
   ...:         itertools.takewhile(
   ...:             lambda item: item,
   ...:             (list(itertools.islice(it, random.randint(min_chunk, max_chunk)))
   ...:              for _ in itertools.repeat(None))))
   ...: 

In [4]: random_chunk(range(10), 2, 4)
Out[4]: [[0, 1], [2, 3, 4], [5, 6, 7], [8, 9]]

In [5]: random_chunk(range(10), 2, 4)
Out[5]: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]

In [6]: random_chunk(range(10), 2, 4)
Out[6]: [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]

In [7]: random_chunk(range(10), 2, 2)
Out[7]: [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]

In [8]: random_chunk(range(10), 1, 2)
Out[8]: [[0, 1], [2, 3], [4], [5], [6], [7, 8], [9]]

In [9]: random_chunk(range(10), 1, 2)
Out[9]: [[0, 1], [2, 3], [4], [5], [6], [7], [8], [9]]

In [10]: random_chunk(range(10), 1, 20)
Out[10]: [[0], [1, 2, 3], [4, 5, 6, 7, 8, 9]]

In [11]: random_chunk(range(10), 1, 20)
Out[11]: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]

In [12]: random_chunk(range(10), 1, 20)
Out[12]: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]

In [13]: random_chunk(range(10), 1, 20)
Out[13]: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]

In [14]: random_chunk(range(10), 1, 20)
Out[14]: [[0], [1, 2, 3, 4, 5, 6, 7, 8], [9]]
cwa
  • 1,092
  • 9
  • 12