Random dividing list keeping original order in new lists

It’s hard for me to formulate my question, so I’ll just show an example.

x = ['abc', 'c', 'w', 't', '3']
a, b = random_split(x, 3)      # first list should be length 3
# e.g. a => ['abc', 'w', 't']
# e.g. b => ['c', '3']

Is there an easy way to split the list into two random samples while maintaining the original order?


Edit: I know that I could use random.sample and then reorder, but I was hoping for a simple, simple, and rigorous method.

Edit 2: Here is another solution, see if you can improve it:

def random_split(l, a_size):
    a, b = [], []
    m = len(l)
    which = ([a] * a_size) + ([b] * (m - a_size)) 
    random.shuffle(which)

    for array, sample in zip(which, l):
        array.append(sample)

    return a, b

3: , O(N*log(N)). , O(N) , , , O(N) , @PedroWerneck . , 100%, .

def random_split(items, size):
  n = len(items)
  a, b = [], []
  for item in items:
    if size > 0 and random.random() < float(size)/n:
      b.append(item)
      size -= 1
    else:
      a.append(item)

    n -= 1

  return a, b
+3
7

, , .

, , RNG, :

>>> import random
>>> x = range(20)
>>> a = []
>>> b = []
>>> for v in x:
...     random.choice((a, b)).append(v)
... 
>>> a
[0, 2, 3, 4, 6, 7, 10, 12, 15, 17]
>>> b
[1, 5, 8, 9, 11, 13, 14, 16, 18, 19]

, , , . , , , .

, , . , :

>>> x = range(20)
>>> b = x[:]
>>> a = sorted([b.pop(b.index(random.choice(b))) for n in xrange(limit)])
>>> a
[0, 1, 5, 10, 15, 16, 17]
>>> b
[2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14, 18, 19]

a, b .

? , , , , :

def random_split(items, size):
    sample = set(random.sample(items, size))
    return sorted(sample), sorted(set(items) - sample)

, , . , Python Timsort n .

, , , :

def random_split(items, size):
    sample = set(random.sample(items, size))
    a = [x for x in items if x in sample]
    b = [x for x in items if x not in sample]
    return a, b

, , (), senderle, O (1) . , .

+4

. , :

def random_split(lst, size):
    import random
    samp = set(random.sample(xrange(len(lst)),size))
    return ([v for i,v in enumerate(lst) if i in samp],
            [v for i,v in enumerate(lst) if i not in samp])

x = ['abc', 'c', 'w', 't', '3']

print random_split(x,3)

(['abc', 't', '3'], ['c', 'w']) #random and retains order
+4

, , . , :

def random_split(seq, n):
    indices = set(random.sample(range(len(seq)), n))
    left_right = ([], [])
    for n, x in enumerate(seq):
        left_right[n not in indices].append(x)
    return left_right

, . , . , . enumerate - , .

def random_split(seq, n):
    rnd_bools = random.sample((0,) * n + (1,) * (len(seq) - n), len(seq))
    left_right = ([], [])
    for b, x in zip(rnd_bools, seq):
        left_right[b].append(x)
    return left_right

. , . , bools. , . random.sample, ; 2- , .

, : bools left_right; , .

, "", - , - :

random_split = lambda seq, n: reduce(lambda a, b: (a[0] + ([b[1]] if not b[0] else []), a[1] + ([b[1]] if b[0] else [])), zip(random.sample((0,) * n + (1,) * (len(seq) - n), len(seq)), seq), ([], []))
+3

:

>>> a = [10,20,30,40,50,60]
>>> keep = sorted(random.sample(range(len(a)),3))
>>> keep
[0, 3, 4]
>>> ([a[i] for i in keep], [a[i] for i in range(len(a)) if i not in keep])
([10, 40, 50], [20, 30, 60])
+1

...

def random_split(L, size):
    index = range(len(L))
    random.shuffle(index)
    return ([L[i] for i in sorted(index[:size])],
            [L[i] for i in sorted(index[size:])])
+1

, random_split .

, , , . , :

import random

x = ['abc', 'c', 'w', 't', '3']

def random_split(x, n):
    k = x[:]
    random.shuffle(k)
    yield sorted(k[:n], key = x.index)
    yield sorted(k[n:], key = x.index)

a, b = random_split(x, 3)

:

>>> a
['c', 'w', 't']
>>> b
['abc', '3']
0

- :

from random import sample
x = ['abc', 'c', 'w', 't', '3']
sample_size = len(x) // 2

sample_set = set(sample(x, sample_size))
split_list = [[x[i] for i in subset] for subset in (sorted(sample_set), sorted(set(x) - sample_set))]
0

All Articles