Wpis z mikrobloga

Jak jest lepiej?
A:
with open('loss.csv', 'rb') as csvfile:
data = [row[1:] for row in csv.reader(csvfile, delimiter='\t')][1:]
data = [filter(None, sublist) for sublist in data]
data = [map(float, sublist) for sublist in data]
B:
with open('loss.csv', 'rb') as csvfile:
data = [map(float, filter(None, row[1:])) for row in csv.reader(csvfile, delimiter='\t')][1:]

Generalnie jak się da to zbijać do jednej linii, czy może rozbijać wszystko na poszczególne kroki? Wolałbym sobie od początku wyrabiać dobre nawyki.
#naukaprogramowania #programowanie #python
  • 17
@Kontestator: Osobiście ani A, ani B. Nie A, bo nadpisywanie tej samej zmiennej kilka razy nie wygląda zbyt ładnie. Nie B, bo ciężko się takie coś czyta. I trochę tak niekonsekwentnie mieszać listy składane oraz filter/map w jednej instrukcji.

Osobiście skłaniałbym się w kierunku czegoś takiego (kropki to oczywiście spacje):

data = [
....[
........float(item)
........for item in row[1:]
........if item
....]
....for row in csv.reader(csvfile, delimiter='\t')
][1:]

Próbowałem się przekonać
Podsumowując: czytelność >> zwięzłość?


@Kontestator: wychodzę z założenia że ktoś mój kod będzie czytał i nie musi to być osoba oblatana w pythonie, niemniej jednak moje rozwiązanie niewiele różni się formą od Twojego pierwowzoru głównie dlatego, że bardzo ładnie podpadło pod "generators pipeline" z linka powyżej (tl;dr - slajdy 1-35 - 1-42) - koncepcja świetna, warto było wspomnieć.
pominąłem kompletnie co tam robiłeś tymi mapami i filterami, nie znam formatu danych
@legolass: Akurat danymi wyjściowymi z csv.reader są stringi, dlatego potem każdą zawartość 'liczba' przerabiam na float. Więc gdy mam w wejściowym pliku zera, to po tym odsiewie nie są usuwane tylko zostaje 0.0
I btw to [1:] na końcu tych instrukcji powinno się dać spokojnie przenieść tuż za koniec wywołania csv.reader zamiast robić to pod sam koniec.

@molski: to działa, ale trzeba dodać list(), wtedy wygląda to tak:

data = [[float(d) for d in row[1:] if d] for row in list(csv.reader(csvfile, delimiter='\t'))[1:]]
bez tego list() się wykrzacza. Zawsze to się przetwarza jedną linię mniej, także dobra uwaga.
bez tego list() się wykrzacza


@Kontestator: właśnie dlatego powinieneś poczytać czym jest iterator. a wykrzacza się bo obrabiasz cały plik, włącznie z pierwszą linią, która w Twoim przypadku najwyraźniej zawiera deklarację nazw pól (raczej nic "floatowalnego") - u mnie sprawę załatwiło reader.next()
@luzny_lori: Dokładny błąd jest taki:
data = [[float(d) for d in row[1:] if d] for row in csv.reader(csvfile, delimiter='\t')[1:]]
TypeError: 'csv.reader' object has no attribute 'getitem_'
Czyli po prostu nie na wszystko co można iterować działa slice. Inny przykład to dictionary.