Sezionare una lista di elementi ad intervalli specifici

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2855
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Sezionare una lista di elementi ad intervalli specifici

Messaggio da DoctorStrange »

Buongiorno a tutti.

Ho questa condizione dalla quale, al momento, mi sfugge come io possa uscirne. Dispongo di una collection di elementi. Questa può essere una lista, un array, un vettore, od un'altra qualunque collection di elementi sequenziali. Questi elementi sono tutte delle semplici stringhe di testo.

Dispongo poi di una seconda lista. Questa seconda lista è semplicemente una lista di interi positivi crescenti. Questi valori sono gli indici ai quali io vorrei che la prima lista venisse sezionata.

Ciò che vorrei ottenere è di separare la prima lista in una serie di liste pi piccole che vengano separate agli indici specificati nella seconda lista.

io programmo usando Scala su un framework Spark, ma sono alla ricerca, piuttosto di un algoritmo, ovvero di un approccio al problema che mi permetta di risolvere, potrò poi tradurlo in scala, python, od altro.

Avete per caso idea di come si possa fare?

Grazie mille.
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da vaeVictis »

Ciao, per cortesia fai un esempio della lista iniziale in input e di quelle che vuoi ottenere in output.
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2855
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da DoctorStrange »

La lista delle stringhe è di questo tipo:

Codice: Seleziona tutto

BEGIN:VCARD
VERSION:2.1
N:;Attiva Servizi;;;
FN:Attiva Servizi
TEL;CELL;PREF:40920
END:VCARD
BEGIN:VCARD
VERSION:2.1
N:API Key;MarketStack;;;
FN:MarketStack API Key
NOTE:---
END:VCARD
BEGIN:VCARD
VERSION:2.1
N:;SHILLING;;;
FN:SHILLING
TEL;WORK:---
TEL;WORK:---
EMAIL;WORK:---
ADR;WORK:;;Piazzale ---
Mentre la lista degli indici, di questo tipo:

Codice: Seleziona tutto

IndiciSeparazione: List[Int] = List(5, 11, 23, 28, 33, 40, 45, 50, 55, 60, 66, 71, 76, 81, 88, 95, 102, 108, 113, 121, 126, 132, 138, 143, 150, 156, 164, 169, 174, 182, 188, 194, 201, 207, 213, 219, 225, 231, 238, 244, 254, 260, 266, 272, 278, 285, 294, 300, 306, 312, 318, 326, 333, 342, 348, 354, 359, 365, 371, 376, 382, 388, 394, 400, 407, 417, 423, 431, 437, 443, 449, 455, 462, 468, 474, 480, 486, 492, 498, 504, 514, 520, 525, 531, 536, 541, 546, 551, 557,
In output vorrei ottenere una lista di liste, all'interno di ognuna delle quali siano contenute tutte le stringhe comprese tra il tag "BEGIN:VCARD" ed il tag "END:VCARD".

Gli indici sono le esatte posizioni dove si trovano tutti i tag di chiusura.
rai
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2842
Iscrizione: domenica 11 maggio 2008, 18:03
Desktop: plasma
Distribuzione: 22.04
Località: Palermo

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da rai »

In output vorrei ottenere una lista di liste, all'interno di ognuna delle quali siano contenute tutte le stringhe comprese tra il tag "BEGIN:VCARD" ed il tag "END:VCARD".
Per essere sicuro di aver capito, dato che non hai fatto l'esempio dell'output desiderato: i delimitatori "BEGIN:VCARD" e "END:VCARD" devono essere esclusi oppure saranno rispettivamente la prima e l'ultima delle stringhe delle sub-liste ?

Comunque, mi sembra che si risolva semplicemente con un ciclo sulla lista di interi per prendere gli indici con cui fare lo slicing della lista di stringhe. Poi le subliste si possono appendere come elementi di una lista o mappare in un dizionario ...

PS
"Semplicemente" se in Python ;-)
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da vaeVictis »

Non ho compreso.
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2855
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da DoctorStrange »

Non saprei come poterlo spiegare piu semplicemente. In ogni caso, io speravo che esistesse una funzione, simile a "split", che potesse accettare una lista di indici, piuttosto che un indice unico, per poter separarae la collection entrante in una serie di liste annidate, ma non credo si possa fare.

Proverò il metodo suggerito da rai, che ringrazio, ma sono un po ostile ai cicli. Avrei preferito un'iterazione map-reduce.
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da vaeVictis »

Codice: Seleziona tutto

Avrei preferito un'iterazione map-reduce
Concordo.

Mi serve capire l'input e l'output concretamente.
Nell'esempio che hai fatto gli indici non "make sense" con l'esempio della lista da elaborare. Quegli indici non esistono.

Mi serve un esempio consistente. Una lista, la lista degli indici, compreso l'output scritto chiaro e tondo.
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2855
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da DoctorStrange »

La lista uscente che vorrei, sarebbe di questo tipo:

Codice: Seleziona tutto

List(List[String]) = List(List(BEGIN:VCARD,VERSION:2.1,N:;Attiva Servizi;;;,FN:Attiva Servizi,TEL;CELL;PREF:40920,END:VCARD),List(BEGIN:VCARD,VERSION:2.1,N:API Key;MarketStack;;;,FN:MarketStack API Key,NOTE:---),List(BEGIN:VCARD,VERSION:2.1,N:;SHILLING;;;,FN:SHILLING,TEL;WORK:---,TEL;WORK:---,EMAIL;WORK:---,ADR;WORK:;;Piazzale ---))
.

Nell'esempio fatto, gli indici corrispondono tutti au tag che mi interessano, per quale motivo sarebbe "no sense"?

Avrei voluto usare una "map" per iterare su tutti gli elementi della collection ma, dal momento che i tag di chiusura non si trovano tutti ad intervalli regolari, non posso usarla per creare la mia lista, devo quindi usare gli indici calcolati nella seconda lista.
rai
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2842
Iscrizione: domenica 11 maggio 2008, 18:03
Desktop: plasma
Distribuzione: 22.04
Località: Palermo

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da rai »

DoctorStrange ha scritto:
venerdì 1 luglio 2022, 12:50
Nell'esempio fatto, gli indici corrispondono tutti au tag che mi interessano
Non esattamente. In Python, adattando i tuoi esempi (aggiunte due righe alla fine delle stringhe di dati che hai postato e presi solo i relativi tre indici) si deve fare ancora un aggiustamento per fare venire bene lo slicing:

Codice: Seleziona tutto

s = """BEGIN:VCARD
... VERSION:2.1
... N:;Attiva Servizi;;;
... FN:Attiva Servizi
... TEL;CELL;PREF:40920
... END:VCARD
... BEGIN:VCARD
... VERSION:2.1
... N:API Key;MarketStack;;;
... FN:MarketStack API Key
... NOTE:---
... END:VCARD
... BEGIN:VCARD
... VERSION:2.1
... N:;SHILLING;;;
... FN:SHILLING
... TEL;WORK:---
... TEL;WORK:---
... EMAIL;WORK:---
... ADR;WORK:;;Piazzale ---
... FOO
... END:VCARD"""
>>> lista_di_stringhe = s.split('\n')
>>> Indici = [5, 11, 23]
>>> output_list, start = [], 0
>>> for n in Indici:
...     stop = n + 1 # <<<<< QUESTO QUI
...     output_list.append(lista_di_stringhe[start:stop])
...     start = stop
... 
>>> for l in output_list:
...     l
... 
['BEGIN:VCARD', 'VERSION:2.1', 'N:;Attiva Servizi;;;', 'FN:Attiva Servizi', 'TEL;CELL;PREF:40920', 'END:VCARD']
['BEGIN:VCARD', 'VERSION:2.1', 'N:API Key;MarketStack;;;', 'FN:MarketStack API Key', 'NOTE:---', 'END:VCARD']
['BEGIN:VCARD', 'VERSION:2.1', 'N:;SHILLING;;;', 'FN:SHILLING', 'TEL;WORK:---', 'TEL;WORK:---', 'EMAIL;WORK:---', 'ADR;WORK:;;Piazzale ---', 'FOO', 'END:VCARD']
>>> 

Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2855
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da DoctorStrange »

Gli indici cominciano sempre a contare da zero. Mi sembra cosa normale. Mai visto che sia diverso da cosi. E' questo ciò che non ti tornava?
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
Messaggi: 8242
Iscrizione: martedì 30 ottobre 2007, 6:33
Desktop: LXDE
Distribuzione: Ubuntu 18.04.1 LTS
Sesso: Maschile
Località: TO
Contatti:

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da crap0101 »

al volo che son di fretta:

Codice: Seleziona tutto

import itertools

fakelist = range(20)
indexes = [3,5,7,9,15]

def keyfunc (lst):
    def _next(seq):
        try: return next(seq)
        except StopIteration: return float('+inf')
    ilst = iter(lst)
    item = _next(ilst)
    call_count = itertools.count()
    def aux (value):
        nonlocal item
        idx = next(call_count)
        if idx > item:
            item = _next(ilst)
        return item
    return aux

print('fakelist:', list(fakelist))
print('indexes:', indexes)
slices = [list(v) for _,v in itertools.groupby(fakelist, key=keyfunc(indexes))]
for lst in slices:
    print(lst)
        
"""
crap0101@orange:~/test$ python3 split_index.py 
fakelist: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
indexes: [3, 5, 7, 9, 15]
[0, 1, 2, 3]
[4, 5]
[6, 7]
[8, 9]
[10, 11, 12, 13, 14, 15]
[16, 17, 18, 19]
crap0101@orange:~/test$
"""
Inoltre mi viene il dubbio che sarebbe meglio un approccio diverso... tipo scorrere il file e dividere subito via i tag start/end piuttoto che gli indici (visto che per ottenerli avrai già fatto una cosa del genere). Poi però magari sei costretto o è ti più comodo fare nell'altro modo, non so, era una considerazione
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2855
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da DoctorStrange »

Crap0101 ti ringrazio tanto. Mi sto studiando con calma il tuo codice, perche non sono pratico di python.

Per quanto riguarda le tue osservazioni, togliere o meno i tag di apertura e chiusura, non mi importa molto. La procedura che ho fatto per estrarre gli indici, in scala è abbastanza semplice. Ho imposto un primo filtro che mi ponesse a true tutte le occorrenze di uno specifico tag. A questo punto ho imposto una funzione "zipWithIndex" che associa un intero crescente a tutti gli elementi della lista, trasformando la lista in una tupla. A questo punto ho estratto da questa tupla tutte le chiave che corrispondessero al true, ovvero alla presenza del tag che mi interessava. Con un secondo filtro ho dunque estratto i soli indici corrispondenti al tag.

Devo ora trovare il modo di suddividere la lista iniziale iin funzione degli indici.

Credo di aver compreso la logica del tuo codice python, ma ci sono allcune cose che non conosco. Mi sto studiando come funziona l'iteratore, e la clusola "nonlocal".

Comunque grazie.
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da vaeVictis »

Ho capito, grazie @crap0101

Usa numpy. In particolare split. L'unica modifica è che devi usare gli offset tra gli elementi e non i loro indici come stai facendo.
È molto al di sotto delle tue capacità, quindi non posto il codice. In caso fai un fischio.
(Ovviamente è reperibile l'algoritmo usato, se devi tradurlo)

Edit
https://stackoverflow.com/questions/627 ... prehension
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
Messaggi: 8242
Iscrizione: martedì 30 ottobre 2007, 6:33
Desktop: LXDE
Distribuzione: Ubuntu 18.04.1 LTS
Sesso: Maschile
Località: TO
Contatti:

Re: Sezionare una lista di elementi ad intervalli specifici

Messaggio da crap0101 »

rigurardo i tag, non era tanto toglierli o tenerli, quanto usare un approccio proprio diverso, in pseudo-quasipronto-codice:

Codice: Seleziona tutto

with open(path) as input:
    stack = []
    entry = []
    inside = 0
    for line in input:
        line = line.strip()
        if line == START_TAG:
            inside = 1
            continue # non tiene START_TAG
        elif line == END_TAG:
            inside = 0
            if entry:
                stack.append(entry)
                entry = []
        if inside:
            entry.append(line)

print(stack)
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 5 ospiti