07 ottobre, 2019

Python, funzioni per stringhe - 1


Alle volte capita che quello che viene dato va quasi bene ma non esattamente come si vorrebbe; per esempio concatenare stringhe:

$ py3
>>> st1 = 'prima stringa'
>>> st2 = 'seconda'
>>> st3 = ''
>>> st4 = 'quarta'
>>> print(st1, '\n', st2, '\n', st3, '\n', st4)
prima stringa
 seconda

 quarta
>>>


Va quasi bene ma no perché Python introduce un blank tra gli elementi che scrive. Sì, ci sono rimedi anche semplici, come usare + per concatenare le stringhe ma forse si riesce a fare meglio (o comunque diversamente).

Con un po' di Stack Overflow, per la dritta, poi modificata, ecco:

>>> lst = ['a', 'b', 'c', 'd']
>>> list(map(' '.join, zip(*([iter(lst)]*(len(lst))))))
['a b c d']
>>>


OK
, nel nostro caso diventa:

>>> lst = [st1, st2, st3, st4]
>>> print(list(map('\n'.join, zip(*([iter(lst)]*(len(lst))))))[0])
prima stringa
seconda

quarta
>>>


Uh!
conviene definire una funzione, strcat(lst, sep) che ritorna la stringa degli elementi di lst separati da sep.
Nota: mi dicono che mettere le parentesi per le funzioni --così strcat()-- non è pythonico; se mi ricordo non lo farò più e scriverò strcat.

>>> def strcat(lst, sep):
...     return list(map(sep.join, zip(*([iter(lst)]*(len(lst))))))[0]
...
>>> strcat(['1', '2', '3', '4', '5'], ' - ')
'1 - 2 - 3 - 4 - 5'
>>> lst = [st1, st2, st3, st4]
>>> stp = strcat(lst, '\n')
>>> stp
'prima stringa\nseconda\n\nquarta'
>>> print(stp)
prima stringa
seconda

quarta
>>>


strcat è composta da una sola istruzione, si può lambdarla:

>>> strcat = lambda lst, sep : list(map(sep.join, zip(*([iter(lst)]*(len(lst))))))[0]
<function <lambda> at 0x7f3332d6d8c8>
>>> strcat(['1', '2', '3', '4', '5'], ' - ')
'1 - 2 - 3 - 4 - 5'
>>>


strcat
adesso funziona solo con liste tutte di tipo str, da modificare rendendo str gli elementi della lista, compito per map:

>>> st = [1, 2, 3, 4, 'stringa', 6, 7.89]
>>> list(map(str, st))
['1', '2', '3', '4', 'stringa', '6', '7.89']
>>>


Inserendo map ottengo la versione corretta

>>> strcat = lambda lst, sep : list(map(sep.join, zip(*([iter(map(str, lst))]*(len(lst))))))[0]

da provare prima di subito:

>>> strcat = lambda lst, sep : list(map(sep.join, zip(*([iter(map(str, lst))]*(len(lst))))))[0]
>>> from math import pi
>>> st = [1, 2, 3, 4, 'stringa', 6, 7.89, pi]
>>> stp = strcat(st, '\n')
>>> print(stp)
1
2
3
4
stringa
6
7.89
3.141592653589793
>>>


OK
. Ci sono 2 condizioni da considerare.

1. La lista contiene sub-liste probabilmente non si ottiene quello sperato:

>>> st = [1, 2, [3, 4], 5, 6]
>>> strcat(st, ' ')
'1 2 [3, 4] 5 6'
>>>


Rendere flat la lista è semplicissimo con altri linguaggi (qualcuno ha detto Racket?) ma per quanto ho visto non facile con Python; su Stack Overflow ho trovato codici per casi semplici ma nessuno tratta il caso generale di liste con liste annidate su più livelli.

Però, ripensandoci, non è una condizione pratica. È come la volpe che scoprì che l'uva non era matura.

2. La lista contiene numeri floating-point (come pi nell'esempio). Devo gestire il formato. Ecco, si può fare  (probabilemnte, forse)  facilmente. Prossimamente, adesso pausa.
🔴

Nessun commento:

Posta un commento