Operando sulle righe e poi sulle colonne di una matrice si produce la duplicazione del codice
-
27-09-2019 - |
Domanda
Ho il seguente codice (Python) per verificare se sono presenti righe o colonne che contengono lo stesso valore:
# 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
Chiaramente, c'è molta duplicazione del codice qui. Come posso rifattorizzare questo codice?
Grazie!
Soluzione
In genere, quando si desidera eseguire il refactoring, prendere frammenti di codice simili e trasformarli in funzioni.Quindi potresti avere una funzione per testare tutte le celle per le quali un indice (riga o colonna) è lo stesso e un'altra funzione che chiama quella funzione su tutte le colonne (o righe).Anche se, come ha sottolineato Pär nel commento alla tua domanda, sarebbe molto più semplice aiutarti se fornissi alcune informazioni su ciò che hai provato.
Ma...un'altra questione separata (forse leggermente correlata) è che il tuo codice non sfrutta le capacità funzionali di Python.Il che va bene, ma giusto perché tu lo sappia, attività come questa in cui devi controllare una serie di diversi elementi di un array (elenco, in realtà) sono spesso tanto più conciso se scritto in modo funzionale.Ad esempio, il tuo esempio potrebbe essere fatto in questo modo:
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)
anche se non è così utile se stai cercando di capire come funziona il codice.
Altri suggerimenti
Per verificare se tutti gli elementi di fila sono uguali, suggerirei di creare un pitone set
della riga e poi controlla se ha un solo elemento.Allo stesso modo per le colonne.
Per esempio.come questo
def testRowWin(b):
for row in b:
if len(set(row)) == 1:
return True
return False
def testColWin(b):
return testRowWin(zip(*b))
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