Python 无嵌套循环的邻接矩阵
我试图为一组团队成员创建一个邻接矩阵。我已经像这样存储了比赛细节-Python 无嵌套循环的邻接矩阵,python,algorithm,Python,Algorithm,我试图为一组团队成员创建一个邻接矩阵。我已经像这样存储了比赛细节- x={'match1':[1,2,3],'match2':[2,3,4],'match3':[3,4,5]} 在这里,每个关键字都有一个值列表,其中包含为那场比赛效力的队员 我试图创建一个邻接矩阵,显示每个队员与另一个队员的比赛次数 输出应该如下所示 1 2 3 4 5 1 1 1 1 0 0 2 1 2 2 1 0 3 1 2 3 2 1 4 0 1 2 2 1 5 0 0 1 1 1 (i,i)矩阵中的元素是该团
x={'match1':[1,2,3],'match2':[2,3,4],'match3':[3,4,5]}
在这里,每个关键字都有一个值列表,其中包含为那场比赛效力的队员
我试图创建一个邻接矩阵,显示每个队员与另一个队员的比赛次数
输出应该如下所示
1 2 3 4 5
1 1 1 1 0 0
2 1 2 2 1 0
3 1 2 3 2 1
4 0 1 2 2 1
5 0 0 1 1 1
(i,i)
矩阵中的元素是该团队成员进行的比赛总数。我已经能够使用计数器
正确计算值
from collections import defaultdict, Counter
if __name__=='__main__':
x = {'match1': [1, 2, 3], 'match2': [2, 3, 4], 'match3': [3, 4, 5]}
d = defaultdict(list)
col_count = dict()
for key, value in x.items():
for i in value:
d[i] += value
for key, value in d.items():
col_count[key] = Counter(d[key])
print(col_count)
输出为:
{1: Counter({1: 1, 2: 1, 3: 1}), 2: Counter({2: 2, 3: 2, 1: 1, 4: 1}), 3: Counter({3: 3, 2: 2, 4: 2, 1: 1, 5: 1}), 4: Counter({3: 2, 4: 2, 2: 1, 5: 1}), 5: Counter({3: 1, 4: 1, 5: 1})}
鉴于x
字典将包含大量键,并且每个键都有一个包含许多元素的列表,我希望避免使用嵌套的for
循环
是否可以将匹配细节存储为任何其他数据类型,以便后续计算不需要嵌套循环
如果字典是最好的方法,是否可以用其他方法计算矩阵?在不修改输入和输出格式的情况下,我不知道如何避免嵌套循环,因为您有按匹配分组的信息,并且希望按播放器提取。实际上,您可以通过在嵌套循环中创建
计数器来避免最后一个循环:
from collections import defaultdict, Counter
if __name__=='__main__':
x = {'match1': [1, 2, 3], 'match2': [2, 3, 4], 'match3': [3, 4, 5]}
d = defaultdict(Counter)
for key, value in x.items():
for i in value:
d[i].update(value)
print(d)
如果可以修改输入,您可以进行如下操作:
from collections import Counter
if __name__=='__main__':
x = {1: [{1, 2, 3}], 2: [{1, 2, 3}, {2, 3, 4}], 3: [{1, 2, 3}, {2, 3, 4}, {3, 4, 5}], 4: [{2, 3, 4}, {3, 4, 5}], 5: [{3, 4, 5}]}
d = {player: Counter([p for match in matches for p in match]) for player, matches in x.items()}
print(d)
在这里,您将嵌套循环替换为dict和列表理解,这应该更有效。球员和比赛可能不是int
s和list
s的int
s,因此这可以做得更可编辑一些。例如:
from collections import defaultdict, Counter
def printMatrix(matrix):
print(' '.join([' |'] + list(map(str, matrix.keys()))))
print('---+-' + '-'*len(matrix)*2)
for row, values in matrix.items():
fmt = ' {row} |'
for col in matrix.keys():
fmt += ' {values[' + str(col) + ']}'
print(fmt.format(row=row, values=values))
class Entity:
def __init__(self):
self._id = None
@classmethod
def register(cls, value):
if value in cls.ids:
raise ValueError("The provided ID is already in use")
cls.ids.add(value)
@classmethod
def unregister(cls, value):
if value is not None:
cls.ids.remove(value)
@property
def id(self):
return self._id
@id.setter
def id(self, value):
if value == self.id:
return
self.register(value)
self.unregister(self.id)
self._id = value
class Player(Entity):
ids = set()
def __init__(self, pid):
super().__init__()
self.id = pid
self.__matches = set()
def __repr__(self):
return 'Player<{}>'.format(self.id)
@property
def matches(self):
return set(self.__matches)
def inscribe(self, match):
if match not in self.__matches:
self.__matches.add(match)
def delist(self, match):
self.__matches.remove(match)
class Match(Entity):
ids = set()
def __init__(self, mid, players):
super().__init__()
self.id = mid
self.__players = set()
self.players = players
for player in players:
player.inscribe(self)
def __repr__(self):
return 'Match<{}>'.format(self.id)
@property
def players(self):
return set(self.__players)
@players.setter
def players(self, value):
for player in self.__players:
player.delist(self)
self.__players = set(value)
for player in self.__players:
player.inscribe(self)
if __name__=='__main__':
players = [Player(i) for i in range(1, 6)]
matches = [Match(i, {players[i-1], players[i], players[i+1]}) for i in range(1, 4)]
for player in players:
print(player, player.matches)
for match in matches:
print(match, match.players)
d = {player.id: Counter([p.id for match in player.matches for p in match.players]) for player in players}
printMatrix(d)
从集合导入defaultdict,计数器
def打印矩阵(矩阵):
打印(“”.join(['|']+list(map(str,matrix.keys())))
打印('-+-'+'-'*len(矩阵)*2)
对于行,矩阵.items()中的值:
fmt='{row}|'
对于矩阵.keys()中的列:
fmt+='{values['+str(col)+']}'
打印(格式(行=行,值=值))
类实体:
定义初始化(自):
self.\u id=None
@类方法
def寄存器(cls,值):
如果cls.ids中的值为:
raise VALUERROR(“提供的ID已在使用”)
cls.ids.add(值)
@类方法
def注销(cls,值):
如果值不是“无”:
cls.ids.remove(值)
@财产
def id(自身):
返回自我。\u id
@id设置器
def id(自身,值):
如果值==self.id:
返回
自寄存器(值)
self.unregister(self.id)
self.\u id=值
职业玩家(实体):
ids=set()
定义初始化(自,pid):
super()。\uuuu init\uuuuu()
self.id=pid
self.\uuu matches=set()
定义报告(自我):
返回“Player”。格式(self.id)
@财产
def匹配(自我):
返回集(自匹配)
def题字(自我,匹配):
如果匹配不在self中。\u匹配:
self.\u匹配。添加(匹配)
def退市(自我、匹配):
自匹配。删除(匹配)
类别匹配(实体):
ids=set()
定义初始(自我、中场、球员):
super()。\uuuu init\uuuuu()
self.id=mid
self.\uu players=set()
self.players=玩家
对于玩家中的玩家:
玩家。题写(自我)
定义报告(自我):
返回“匹配”。格式(self.id)
@财产
def玩家(自我):
返回集(自选球员)
@二传手
def玩家(自我、价值):
对于自己的玩家。\u玩家:
球员退市(自我)
self.\uu players=set(值)
对于自己的玩家。\u玩家:
玩家。题写(自我)
如果“名称”=“\uuuuuuuu主要”:
players=[范围(1,6)内的Player(i)代表i]
matches=[Match(i,{players[i-1],players[i],players[i+1]})为范围(1,4)内的i进行匹配]
对于玩家中的玩家:
打印(球员,球员,比赛)
对于匹配中的匹配:
打印(比赛,比赛,球员)
d={player.id:Counter([p.id代表player中的match.matches代表p代表match.players])代表player中的player}
打印矩阵(d)
printMatrix()
函数只是我用来将输出漂亮地打印到屏幕上的一个助手
实体
类避免了玩家
和匹配
类都需要的重复代码,因为它们都有唯一的ID。构造函数创建一个空的\u id
属性。register()
和unregister()
方法处理从类属性IDs
添加和删除id。它还声明了带有getter和setter的id
属性。子类只需要在构造函数中调用super()。\uuuu init\uuuu()
,并在想要强制ID唯一性的级别创建ids
class属性,就像Player
和Match
所做的那样
Player
类还具有matches
实例只读属性,该属性分别由inscribe()
和delist()方法填充和取消填充。Match
类具有带有getter和setter方法的players
属性
首先,使用两种列表理解创建玩家
和比赛
(请记住,列表从位置0开始,因此ID为1的玩家
位于玩家[0]
)并打印其对应关系(他们为玩家和参与比赛的玩家播放的比赛)
由于两者都保留了对另一种类型的引用,我们可以获得构建计数器的指令所需的所有信息,您刚刚从玩家那里请求我认为矩阵中有一个输入错误,5
应该是1
,不应该吗?错误已经纠正了。row=2 path=2 result=2是什么意思?玩家2打了两场比赛。我想你不能