FlatMap - pythonic way

0

Programuję zaowodowo w javie,js i php, teraz piszę sobie domowy tool w pythonie żeby poznać język, jednak natrafiłem na problem, i chciałbym poznać pythonic-way.

Otóż mam sobie listę

lista = ['Foo', 'Bar', 'Lorem\nIpsum\ndolor\nsit\namet'] 

i chciałbym, to co na w javie możnaby zrobić flatMap(word-> word.split("\n")), żeby dostać efekt

result = ['Foo', 'Bar', 'Lorem', 'Ipsum', 'dolor', 'sit', 'amet']

Tylko nie chcę robić map+split, a potem jakoś flatten'ować tą listę, bo czuję że nie tak się to robi w pythonie.

To co zrobiłem i nie działa:
Wiem że jest operator destruct w pythonie, więc możaby zrobić tak:

lista = ['Foo', 'Bar', *(tutaj splitowanie tego stringa)]

ale zrobienie tego dla dynamicznych danych juź mi nie działa:

return [*(_split(name)) for name in params.values()]

spodziewam się że destruct nie może być użyty w taki dynamiczny sposób? Nie wiem.

Jak to zrobić?

PS: Oczywiście googlowałem "python flat map" ale dostawałem albo jakieś zagnieżdżone pętle (to już folę map+split+flatten), albo jakieś overengineeringi ze ściągnaiem dodatokwych modułów.

2

Dobra, znalazłem.

Pythonic way to nawidoczniej:

flat = [y for x in my_list for y in x]
0

Jeśli szukasz wyjaśnienia dlaczego nie można uzywać star-expressions w wyrażeniu listowym, jest tak dlatego, że jest to szczególny przypadek wywołania funkcji, gdzie chcesz wypełnić resztę argumentów, z tym że tutaj akurat tą funkcją jest konstruktor listy. Dlatego taki zapis w wyrażeniu listowym ma mały sens.

2

Warto też wspomnieć, że często nie ma sensu szukać na siłę cwanych one-linerów, bo liczy się czytelność, a nie zwięzłość. Jak napiszesz

output = []
for s in lista:
    output.extend(s.split('\n'))

to ci raczej żaden Pythonista głowy nie urwie

0
Spearhead napisał(a):

to ci raczej żaden Pythonista głowy nie urwie

Urwie, to aż się prosi o użycie list comprehension.

0
Spearhead napisał(a):

Warto też wspomnieć, że często nie ma sensu szukać na siłę cwanych one-linerów, bo liczy się czytelność, a nie zwięzłość. Jak napiszesz

output = []
for s in lista:
    output.extend(s.split('\n'))

to ci raczej żaden Pythonista głowy nie urwie

Nie użyjesz tego jako expression, będziesz musiał to wsadzić do funkcji żeby tego używać jakoś sensownie. Poza tym to wygląda bardzo proceduralnie (jak np w c++, javie lub innych). Jestem przekonany że w wyżej poziomowym języku takim jak python jest od tego dedykowana składnia.

1

@TomRiddle:
Alternatywą do list-comprehension może być jeszcze chain.

from itertools import chain
it = chain.from_iterable(map(_split, lista)) # zwraca generator
list(it)
# >> ['Foo', 'Bar', 'Lorem', 'Ipsum', 'dolor', 'sit', 'amet']

Edit: W sumie jest też taka biblioteczka toolz, która próbuje łatać dziury w bibliotece standardowej i ma mapcat.

2

Proponuję tak:

from functools import reduce
from operator import concat

sublist = ['Foo', 'Bar', 'Lorem\nIpsum\ndolor\nsit\namet']
flat = reduce(concat, [x.split('\n') for x in sublist])

albo:

from itertools import chain

sublist = ['Foo', 'Bar', 'Lorem\nIpsum\ndolor\nsit\namet']
flat = list(chain.from_iterable(x.split('\n') for x in sublist))

albo:

sublist = ['Foo', 'Bar', 'Lorem\nIpsum\ndolor\nsit\namet']
flat = sum([x.split('\n') for x in sublist], [])

Chociaż te ostatnie, to taki żart. Pierwsze chyba będzie najszybsze, jeżeli to ma jakieś znaczenie.

1
Haskell napisał(a):

Proponuję tak:

flat = reduce(concat, [x.split('\n') for x in sublist])
flat = sum([x.split('\n') for x in sublist], [])

Te propozycje są O(N**2).

0
Mózg napisał(a):

Te propozycje są O(N**2).

Zgadza się, ale póki co tylko takie się pojawiły, więc masz okazję się wykazać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0