为for循环随机化2个列表

时间:2014-02-06 21:01:35

标签: python list loops

假设我有2个相同大小的列表以及以下代码:

list1 = ['tom', 'mary', 'frank', 'joe']
list2 = [1, 2, 3, 4]

for names, numbers in zip(list1, list2):
    print names, numbers

对于for循环的每次迭代,我如何使用每个列表中的随机索引?

沿着类似的说明,如果我有两个不同大小的列表:

list1 = ['tom', 'mary', 'frank', 'joe', 'john', 'barry']
list2 = [1, 2, 3, 4]

与第一个示例一样,我如何使用随机索引,但这次,一旦到达list2之外的项目的第一个索引,就开始为list1中的剩余项目再次随机化list2的索引?在这种情况下,zip不再是正确的使用方法吗?

frank 3
tom 4
john 2
mary 1
barry 4
joe 2

^所需的输出(但完全随机)

7 个答案:

答案 0 :(得分:6)

这有效,但有点冗长:

import random

def shuffled(seq):
  copy = list(seq)
  random.shuffle(copy)
  return copy

def rand_repeat(seq):
  while True:
    for el in shuffled(seq):
      yield el

list1 = ['tom', 'mary', 'frank', 'joe', 'john', 'barry']
list2 = [1, 2, 3, 4]

print zip(shuffled(list1), rand_repeat(list2))

答案 1 :(得分:3)

list1 = ['tom', 'mary', 'frank', 'joe', 'john', 'barry']
list2 = [1, 2, 3, 4]

random.shuffle(list2)
for name, number in zip(list1, itertools.cycle(list2)):
    print name, number

答案 2 :(得分:3)

我会循环,直到第一个列表用尽,从list1中随机选择列表1中的项目:

while list1:
    for item in random.sample(list2, len(list2)):
        if not list1:
            break
        name = list1.pop(random.randrange(0, len(list1)))
        print name, item

Nota:random.sample(list2, len(list2))是一个返回新列表的洗牌。

修改

错过休息,导致崩溃

答案 3 :(得分:1)

如果你想以随机的方式有效地迭代一些列表,有很多可能的解决方案,但我建议你只需将你的list转换为set,然后从中随机抽样第二个清单。你可以这样做:

for element in set(list1):
    print element, random.choice(list2)

如果你希望它在不同的迭代中真正随机,你总是可以使用random.shuffle函数,但由于这个文档已被很好地记录并在其他地方引用,我认为你可能想要一个不同旋转的答案而不是

如果你真的想要实现你描述的第二个元素的随机抽样,我想我会为它自己创建一个类。像这样:

class RandomList(object):
    def __init__(self, master_list):
        self.current_list = master_list
        self.master_list = master_list

    def __iter__(self):
        if not self.current_list:
            self.current_list = self.master_list
        index = random.choice(range(len(self.current_list)))
        value = self.current_list.pop(index)
        return value

答案 4 :(得分:1)

我注意到你不希望按索引链接列表项并按随机方式生成所有内容但是这个答案对于想要压缩两个不均匀长度列表并通过随机选择较小值来填充空白空间的人会有所帮助列表。


使用izip_longestrandom.choice

list1 = ['tom', 'mary', 'frank', 'joe', 'john', 'barry']
list2 = [1, 2, 3, 4]

izip_longest就像zip从两个迭代中生成元组但如果迭代的长度不均匀,则使用None填充缺失值(默认情况下):

>>> list(izip_longest(list1, list2))
[('tom', 1), ('mary', 2), ('frank', 3), ('joe', 4), ('john', None), ('barry', None)]

然后,您可以在列表理解中检查None的值并使用random.choice

>>> l = [(n, v if v else random.choice(list2)) for n,v in izip_longest(list1, list2)]
>>> l
[('tom', 1), ('mary', 2), ('frank', 3), ('joe', 4), ('john', 2), ('barry', 4)]

要随机化元组的顺序,您可以使用random.shuffle

>>> random.shuffle(l)
>>> l
[('mary', 2), ('john', 1), ('barry', 2), ('joe', 4), ('tom', 1), ('frank', 3)]

答案 5 :(得分:0)

我认为最紧凑的方式是使用itertools.productrandom.choice

import random, itertools
>>> def randomizer(a, b):
...     prod = list(itertools.product(a, b))
...     while True:
...         yield random.choice(prod)
...
>>> r = randomizer('tom mary frank joe'.split(' '), range(1, 5))
>>> r.next()
('mary', 2)
>>> r.next()
('frank', 2)
>>> r.next()
('mary', 4)
>>> r.next()
('frank', 3)
>>> r.next()
('joe', 1)

您可以像这样解压缩元组:

name, index = r.next()

请注意,这将存储大小为len(a) * len(b)的中间列表,因此从空间角度来看,它不是最有效的。

答案 6 :(得分:0)

另一种方法:

from collections import deque
from random import shuffle
from copy import copy

def make_deque(vals):
        back = copy(vals)
        shuffle(back)
        return deque(back)

prime = ['a','b','c','d','e']
support = [1,2,3,4]
deq = make_deque(support)
shuffle(prime)

for p in prime:
        try:
                s = deq.pop()
        except IndexError:
                deq = make_deque(support)
                s = deq.pop()
        print str(p) + " " + str(s)