2017-10-23 2 views
0

팀 플레이어 세트에 대한 인접 행렬을 생성하려고합니다. 이 같은 경기 세부 정보를 저장했습니다.중첩 루프가없는 인접 행렬

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) 요소 같아야는 또 다른 팀 멤버와 함께 연주 얼마나 많은 일치 보여주는 인접 행렬을 만들려고 해요 해당 팀원이 수행 한 총 경기 수입니다. Counter을 사용하여 정확하게 값을 계산할 수있었습니다.

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 루프의 사용을 피하고자 .

다음 세부 계산에 중첩 루프가 필요 없도록 일치 세부 정보를 다른 데이터 형식으로 저장할 수 있습니까?

사전이 가장 좋은 방법이라면 매트릭스를 다른 방식으로 계산할 수 있습니까?

+0

매트릭스에 오타가 있다고 생각합니다. '5'는 '1'이어야합니다. 그렇지 않습니까? – Adirio

+0

오류가 수정되었습니다. – Misha

+0

행 = 2 경로 = 2 결과 = 2가 무엇을 의미합니까? –

답변

1

입력 및 출력 형식을 수정하지 않고 정보를 그룹화하여 그룹화 한 루프가 발생하지 않도록하고 해당 정보를 플레이어별로 추출하려고합니다. 당신이를 교환 어디

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) 

: 입력하면 같은 뭔가를 갈 수 수정할 수 있습니다 경우

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) 

: 당신이 할 실제로 수있는 것은 중첩 루프 내부의 Counter을 작성하여 마지막 루프를 피할 수있다 더 효율적이어야하는 dict 및 list comprehension을위한 중첩 된 루프. 아마도 선수와 경기는 intlists가 int입니다. 그래서 조금 더 붉게 할 수 있습니다. 예를 들어 :

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) 

printMatrix() 기능은 내가 화면에 출력을 꽤 - 인쇄 제작 단지 도우미입니다.

Entity 클래스는 PlayerMatch 클래스 둘 다에 고유 한 ID가 있으므로 두 코드에 필요한 중복 코드를 방지합니다. 생성자는 빈 _id 특성을 만듭니다. register()unregister() 메서드는 클래스 속성 ids에서 ID를 추가하고 제거하는 작업을 처리합니다. 또한 getter 및 setter로 id 속성을 선언합니다. 어린이 클래스는 생성자에서 super().__init__()을 호출하고 PlayerMatch과 같이 ID 고유성을 적용하려는 수준에서 ids 클래스 속성을 만들면됩니다.

클래스에는 matches 인스턴스 추가 읽기 전용 속성이 있으며 각각 inscribe()delist() 메서드로 채워져 있습니다. Match 클래스에는 getter 및 setter 메서드가있는 players 속성이 있습니다.

첫째는 playersmatches (ID 1과 Playerplayers[0] 오도록리스트 위치 0에서 시작 기억) 두 지능형리스트로 만들어 대응 관계와 함께 인쇄된다 (그들은 플레이어와 플레이어가 플레이 일치하는지 성냥을 위해 참가하십시오).

두 유형 모두 다른 유형에 대한 참조를 유지하므로 players에서 요청한 dictCounter 인 빌드에 필요한 모든 정보를 얻을 수 있습니다.

+0

어떻게 입력을 수정할 수 있습니까? 목록 요소를 저장할 수있는 방법을 알 수 없습니다. 목록의 목록으로 저장할 수 있지만 다시 중첩 된 루프가 필요합니다. – Misha

+0

@Misha 나는 인스턴스가 서로를 참조하는 두 개의 클래스를 사용하여 데이터를 구조화하는 방법을 포함하도록 내 대답을 편집했습니다. 경기 결과 나 플레이어 통계와 같은 속성을 더 많이 포함 할 것입니다. – Adirio

+0

'printMatrix' 함수의 일부분을 이해할 수 없습니다. 'fmt = '{row} |'와'fmt + = '{values ​​['+ str (col) + ']}'를 이해할 수 있도록 문서를 보내거나 도움을 줄 수 있습니까? 도움을 구하려고했지만이 라인을 이해하는 데 도움이되는 것을 찾을 수 없었습니다. – Misha

관련 문제