2010-06-16 5 views
0

I ont le code ci-dessous (python) pour vérifier s'il y a des rangées ou des colonnes qui contiennent la même valeur:de fonctionnement sur les lignes et sur les colonnes d'une matrice produit duplication de code

# Test rows -> 

     # Check each row for a win 
     for i in range(self.height):     # For each row ... 

      firstValue = None       # Initialize first value placeholder 

      for j in range(self.width):     # For each value in the row 
       if (j == 0):        # If it's the first value ... 
        firstValue = b[i][j]      # Remember it 
       else:          # Otherwise ... 
        if b[i][j] != firstValue:     # If this is not the same as the first value ... 
         firstValue = None       # Reset first value 
         break          # Stop checking this row, there's no win here 

      if (firstValue != None):     # If first value has been set 
                  # First value placeholder now holds the winning player's code 
       return firstValue       # Return it 

    # Test columns -> 

     # Check each column for a win 
     for i in range(self.width):     # For each column ... 

      firstValue = None       # Initialize first value placeholder 

      for j in range(self.height):    # For each value in the column 
       if (j == 0):        # If it's the first value ... 
        firstValue = b[j][i]      # Remember it 
       else:          # Otherwise ... 
        if b[j][i] != firstValue:     # If this is not the same as the first value ... 
         firstValue = None       # Reset first value 
         break          # Stop checking this column, there's no win here 

      if (firstValue != None):     # If first value has been set 
                  # First value placeholder now holds the winning player's code 
       return firstValue       # Return it 

De toute évidence, il est beaucoup de duplication de code ici. Comment refactoriser ce code?

Merci!

Répondre

2

Généralement, lorsque vous voulez refactoriser, prendre des extraits de code similaires et les transformer en fonctions. Vous pouvez donc avoir une fonction pour tester toutes les cellules pour lesquelles un index (ligne ou colonne) est le même, et une autre fonction qui appelle cette fonction sur toutes les colonnes (ou lignes). Bien que Pär l'ait souligné dans le commentaire sur votre question, il serait beaucoup plus facile de vous aider si vous donniez des informations sur ce que vous avez essayé. Mais ... une autre question distincte (peut-être légèrement liée) est que votre code ne tire pas parti des capacités fonctionnelles de Python. Ce qui est bien, mais juste pour que vous sachiez, des tâches comme celle-ci où vous devez vérifier un tas d'éléments différents d'un tableau (liste, en fait) sont souvent plus concis lorsqu'il est écrit fonctionnellement. Par exemple, votre exemple pourrait être fait comme ceci:

f = lambda x,y: x if x == y else False 
# for Python <= 2.4 use this instead: 
# f = lambda x,y: x == y and x or False 
# test rows 
[reduce(f,r) for r in array] 
# test columns 
reduce(lambda r,s: map(f,r,s), array) 

bien que ce soit pas utile si vous essayez de comprendre comment le code fonctionne.

+0

Pourquoi faire 'x == y et x ou False' quand vous pouvez faire' x si x == y sinon False'. Ou mieux encore, écrivez-le en tant que «def» et évitez de l'emballer en une seule ligne :) – detly

+0

C'est une fonction exceptionnellement courte qui fait quelque chose de très simple - ce genre de choses peut parfois être plus clair que lambda. Le code d'emballage sur une ligne n'est pas toujours une mauvaise chose. Et la syntaxe 'x if x == y else False' n'a été ajoutée que dans Python 2.5; 'x == y et x ou False' est beaucoup plus ancien (et plus compatible). Vous avez raison de dire que la nouvelle syntaxe est probablement meilleure si vous pouvez l'utiliser, cependant. –

2

Pour vérifier si tous les éléments d'une ligne sont égaux, je suggère de construire un python set de la ligne et ensuite vérifier s'il n'a qu'un seul élément. De même pour les colonnes.

E.g. comme ceci

def testRowWin(b): 
    for row in b: 
     if len(set(row)) == 1: 
      return True 
    return False 

def testColWin(b): 
    return testRowWin(zip(*b)) 
+0

+1 pour 'testRowWin (zip (* b))'. Je pense que votre première fonction pourrait être implémentée 'any (len (set (row)) == 1 pour row dans b)' si vous vouliez être concis comme ça. –

+0

@David: Bon indice, merci. Comme vous l'avez mentionné dans un autre commentaire sur cette page, la rétrocompatibilité compte parfois, et 'any' n'a pas été introduit jusqu'à 2.5 :) –

+0

vrai, j'avais complètement oublié que' any' était aussi nouveau! –

1
def test_values(self, first, second, HeightWidth): 
    for i in range(first): 
     firstValue = None 
     for j in range(second): 
      (firstDimension, secondDimension) = (i, j) if HeightWidth else (j, i) 
      if secondDimension == 0: 
       firstValue = b[firstDimension][secondDimension] 
      else: 
       if b[firstDimension][secondDimension] != firstValue: 
        firstValue = None 
        break 
    return firstValue 

firstValue = test_values(self, self.height, self.width, true) 
if firstValue: 
    return firstValue 

firstValue test_values(self, self.width, self.height, false) 
if firstValue: 
    return firstValue 
Questions connexes