Ho dati 2D a cui voglio applicare più funzioni. Il codice effettivo utilizza xlrd
e un file .xlsx
, ma fornirò il seguente pannello della caldaia in modo che l'output sia facile da riprodurre.Applicare più funzioni con la mappa
class Data:
def __init__(self, value):
self.value = value
class Sheet:
def __init__(self, data):
self.data = [[Data(value) for value in row.split(',')] for row in data.split('\n')]
self.ncols = max(len(row) for row in self.data)
def col(self, index):
return [row[index] for row in self.data]
Creazione di un foglio:
fake_data = '''a, b, c,
1, 2, 3, 4
e, f, g,
5, 6, i,
, 6, ,
, , , '''
sheet = Sheet(fake_data)
In questo oggetto, data
contiene una matrice 2D di stringhe (per il formato di input) e voglio eseguire operazioni sulle colonne di questo oggetto. Niente fino a questo punto è nel mio controllo.
voglio fare tre cose a questa struttura: trasporre le righe in colonne, estrarre value
da ogni oggetto Data
, e provare a convertire il valore in una float
. Se il valore non è un float
, dovrebbe essere convertito in uno str
con spazio bianco spogliato.
from operators import attrgetter
# helper function
def parse_value(value):
try:
return float(value)
except ValueError:
return str(value).strip()
# transpose
raw_cols = map(sheet.col, range(sheet.ncols))
# extract values
value_cols = (map(attrgetter('value'), col) for col in raw_cols)
# convert values
typed_cols = (map(parse_value, col) for col in value_cols)
# ['a', 1.0, 'e', 5.0, '', '']
# ['b', 2.0, 'f', 6.0, 6.0, '']
# ['c', 3.0, 'g', 'i', '', '']
# ['', 4.0, '', '', '', '']
Si può notare che map
viene applicata ad ogni colonna due volte. In altre circostanze, voglio applicare una funzione a ciascuna colonna più di due volte.
C'è un modo migliore per mappare più funzioni alle voci di un iterabile? Più oltre, c'è via per evitare la comprensione del generatore e applicare direttamente la mappatura a ogni singolo iterabile? O c'è un modo migliore ed estensibile per affrontare tutto questo insieme?
Si noti che questa domanda non è specifica per xlrd
, è solo il caso di utilizzo corrente.
promemoria: 'map (f, carta (g, xs))' ha lo stesso output 'map (comporre (f, g), xs)'; il primo eseguirà due volte la raccolta, ma quest'ultimo verrà ripetuto solo una volta. – naomik
@naomik Giusto, vorrei solo che ci fosse un built-in 'compose' credo. –
Jared, puoi facilmente crearne uno tuo. 'compose' non è altro che' lambda f, g: lamda x: f (g (x)) '. Oppure usa semplicemente 'map (lambda x: f (g (x)), xs)' – naomik