首页 > 解决方案 > 从元组组合对列表中挑选,使得每个元组元素至少出现两次

问题描述

假设我有一个元组列表,其元素都是列表中所有可能的配对:

IE matchup=[('Mike','John'),('Mike','Mary'),('Mike','Jane'),('John','Mary'),('John','Jane'),('Mary','Jane')...]

我想减少列表,以便每个人的名字出现两次,无论他们是配对中的第一个元素还是第二个元素。如果不这样做就无法创建新对,则可能会多次选择元组元素。

提前致谢。

编辑:最初在列表中,我使用 for 循环将每个人与另一个人随机配对 ala:

list=["John","Mike","Mary","Jane"]
pairing=[]
for person in list:
    for i in range(2):
        person2=random.sample(list(list),1)
        this_match=str(person)+str(person2)
        while this_match in pairing:
            person2=random.sample(list(list),1)
            this_match=str(person)+str(person2)
        pairing.append(this_match)

这导致了同一个人的重复。我的第二次尝试是这样的:

from itertools import combinations
import pandas as pd
from collections import Counter

possible_games = combinations(list, 2)

games = list(possible_games)
dupe_check=Counter(games)
print(dupe_check)
print (games, len(games))

但是,我不能将每个元组的元素减少到尽可能接近两倍。

一种可能的输出可能如下所示:

[('Mike','John'),('Mike','Mary'),('John','Mary'),("Mary","Jane"),("Jane","Mike")]

约翰出现了两次。简出现了两次。为了让简出现两次,迈克出现了三次。玛丽出现了三次,简出现了两次。

标签: python-3.xtuplesuniquecombinations

解决方案


以下代码将完全解决您的问题。result将在此代码中为您提供答案。

import itertools
import random
import numpy as np

# lst is a list of names that I have chosen.
lst = ['Apple', 'Boy', 'Cat', 'Dog', 'Eagle']

# create a list of tuples (pairs of names).
matchup = list(itertools.product(lst, lst)) 

# randomly shuffle the pairs of names.
random.shuffle(matchup)


def func(inp):
    out = []
    out += [ inp[0] ]

    # Unique array of names.
    unq = np.unique( (zip(*inp))[0] )

    # Stores counts of how many times a given name features in the final list of tuples.
    counter = np.zeros(len(unq))

    indx0 = np.where( out[0][0]==unq )[0][0]
    indx1 = np.where( out[0][1]==unq )[0][0]    
    counter[indx0]+=1
    counter[indx1]+=1    

    reserve = []

    #first try of filling output list with tuples so that no name enters the output list more than once.   
    for i in range(1,len(matchup)):
        tup = matchup[i]

        indx0 , indx1 = np.where(tup[0]==unq)[0][0], np.where(tup[1]==unq)[0][0]

        temp = counter.copy()

        temp[indx0]+=1
        temp[indx1]+=1

        if ( (temp[indx0]<=2) and (temp[indx1]<=2) ):
            out += [tup]
            counter[indx0]+=1
            counter[indx1]+=1

        else: reserve += [tup]     

    #A tuple element may be selected more than twice if it is not possible to create a new pair without doing so.    
    while(np.any(counter==1)):
        tup = reserve[0]

        indx0 , indx1 = np.where(tup[0]==unq)[0][0], np.where(tup[1]==unq)[0][0]

       # Create a copy of counter array. 
       temp = counter.copy()

        if ( (temp[indx0]<2) or (temp[indx1]<2) ):
            out += [tup]
            counter[indx0]+=1
            counter[indx1]+=1 

        reserve.pop(0)    

    return out  

result = func(matchup)
print (result)

的输出result在不同的运行中会有所不同,因为元组(名称)列表在每次运行中随机打乱。结果的一个例子如下。

[('Cat', 'Dog'), ('Eagle', 'Boy'), ('Eagle', 'Dog'), ('Cat', 'Boy'), ('Apple', 'Apple')]      

推荐阅读