python-3.x - 从元组组合对列表中挑选,使得每个元组元素至少出现两次
问题描述
假设我有一个元组列表,其元素都是列表中所有可能的配对:
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")]
约翰出现了两次。简出现了两次。为了让简出现两次,迈克出现了三次。玛丽出现了三次,简出现了两次。
解决方案
以下代码将完全解决您的问题。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')]
推荐阅读
- cordova - 科尔多瓦 - 状态栏中的图像
- scala - 如何在 play framework 2.5 中将 DBApi 注入到 trait 组件中?
- c# - 如何在后台运行异步任务?
- ruby-on-rails - 多选多选 Ruby on Rails 不创建关联记录
- visual-studio-code - 旧产品图标?
- python - 带有seaborn的for循环不显示所有图
- apache-kafka-streams - Kafka Streams - 状态存储的卷导致“无法删除状态目录”错误
- apache-drill - 无法启动 Drill:线程“main”中的异常 org.apache.drill.exec.exception.DrillbitStartupException:无法获取规范主机名
- c# - 如何将 ASP.NET MVC 核心视图和 ASP.NET WEB API 控制器分离到单独的项目中?
- python - 用条件填充数据框中的空单元格