【问题标题】:Pick from list of tuple combination pairs such that each tuple element appears at least twice从元组组合对列表中挑选,使得每个元组元素至少出现两次
【发布时间】:2018-11-09 05:42:37
【问题描述】:

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

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")]

约翰出现了两次。简出现了两次。为了让简出现两次,迈克出现了三次。 Mary 出现了 3 次,Jane 出现了 2 次。

【问题讨论】:

  • 您尝试了什么,还添加了输出的外观,应该更清晰。
  • 在你可能的输出中,Mike 和 Mary 重复了 3 次,为什么
  • 因为必须有人与 Jane 配对才能重复两次,所以随机选择了 Mike。或者,约翰可能被选中,因为他只出现了两次。玛丽不会被选中,因为她已经出现了 3 次。
  • 我认为它是一个 dfs 图,其中节点是名称:)

标签: python-3.x tuples unique combinations


【解决方案1】:

我猜准确两次获取每个名称的最简单方法如下:

lst = ["John", "Mike", "Mary", "Jane"]  # not shadowing 'list'

pairs = list(zip(lst, lst[1:]+lst[:1]))
pairs
# [('John', 'Mike'), ('Mike', 'Mary'), ('Mary', 'Jane'), ('Jane', 'John')]

这实质上是围绕列表并将每个元素与其两个邻居配对。如果您需要更多随机性,您可以预先打乱列表或将列表分成块并将其应用于块。

【讨论】:

    【解决方案2】:

    以下代码将完全解决您的问题。 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')]      
    

    【讨论】:

    • 当你有机会测试这个时告诉我,@machump :)
    • 嗨@Siddharth Satpathy,感谢您处理此代码,看起来投入了大量工作。您的代码中有一个小问题,它允许元素与自身匹配。但主要是,我会接受前面的答案,因为它对我微弱的头脑来说更容易理解。谢谢!
    • machump:别担心,你的问题很有趣。 @schwobaseggl 的回答也很棒。快乐编码 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多