如何从单个列表中构建独特的随机对

How to build unique random couple from a single list

我想在一个列表中随机找到不同成员的情侣。

这是我的代码:

import random

def alea_couple(members):
    couples = []
    for p in members:
        possibles = [r for r in members if r!=p and r not in [elem[1] for elem in couples]] 
        couples.append((p, random.choice(possibles)))
    return couples

my_members = ["member1", "member2", "member3", "member4"]
random.shuffle(my_members)
alea_couple(my_members)

[('member2', 'member1'),
 ('member3', 'member4'),
 ('member1', 'member3'),
 ('member4', 'member2')]

我相信 itertools.combinations

有更好更优雅的方式来做到这一点

你有什么建议吗?

试试 itertools.permutations:

import itertools
import random

def alea_couple(members):
    perms = [p for p in itertools.permutations(members) if not any(x==y for x, y in zip(members, p))]
    return list(zip(members, random.choice(perms)))

>>> alea_couple(["member1", "member2", "member3", "member4"])
[('member1', 'member4'),
 ('member2', 'member3'),
 ('member3', 'member1'),
 ('member4', 'member2')]

>>> alea_couple(["member1", "member2", "member3", "member4"])
[('member1', 'member4'),
 ('member2', 'member3'),
 ('member3', 'member2'),
 ('member4', 'member1')]

我认为这是一个实现 O(n),但性能可能无关紧要(请参阅下面的注释)。首先洗牌,然后按随机数量旋转。我已经 ,所以这里有类似的东西:

import random
import collections

def random_rotation(lst):
    """
    Rotate a list by a random amount and return a deque.

    Similar to "random.shuffle()", but ensures that all elements will move.
    """
    n = random.randrange(1, len(lst))
    d = collections.deque(lst)
    d.rotate(n)
    return d

def alea_couple(members):
    members = random.sample(members, k=len(members))  # Copy and shuffle in one
    pairs = random_rotation(members)
    return list(zip(members, pairs))

示例输出:

>>> my_members = ["member1", "member2", "member3", "member4"]
>>> alea_couple(my_members)
[('member4', 'member3'),
 ('member1', 'member4'),
 ('member2', 'member1'),
 ('member3', 'member2')]
>>> alea_couple(my_members)
[('member3', 'member4'),
 ('member2', 'member1'),
 ('member4', 'member3'),
 ('member1', 'member2')]

来自the docs的注释:

even for small len(x), the total number of permutations of x can quickly grow larger than the period of most random number generators. This implies that most permutations of a long sequence can never be generated. For example, a sequence of length 2080 is the largest that can fit within the period of the Mersenne Twister random number generator.