2013-12-10 7 views
8

Sto leggendo un file e disfare ogni riga come questa:modo idiomatico per decomprimere lista lunghezza variabile delle dimensioni massime n

for line in filter(fh): 
    a, b, c, d = line.split() 

Tuttavia, è possibile che la linea può avere più o meno colonne rispetto alle variabili I desidero disfare i bagagli. Nel caso in cui ci sono meno, vorrei assegnare None alle variabili penzolanti, e nel caso in cui ci sono più, mi piacerebbe ignorarli. Qual è il modo idiomatico per fare questo? Sto usando Python 2.7.

+0

Buona domanda. Spero che qualcuno mi provi male, ma penso che tu abbia bisogno di più di una dichiarazione per quello ... È fattibile in Lua per quanto mi ricordo ... – dsign

+0

vedi https://stackoverflow.com/questions/ 5333680/extended-tuple-unpacking-in-python-2 – n611x007

risposta

12

Fissare la lunghezza della lista, imbottitura con None.

def fixLength(lst, length): 
    return (lst + [None] * length)[:length] 
-1

Qualcosa di simile funziona per qualsiasi iteratore iteratore. Se passerai sempre un elenco, puoi rimuovere la parte islice.

from itertools import islice 
def solve(seq, n): 
    lis = list(islice(seq, n)) 
    return lis + [None]*(n - len(lis)) 
... 
>>> a, b, c, d = solve(range(2), 4) 
>>> a, b, c, d 
(0, 1, None, None) 
>>> a, b, c, d = solve('qwe', 4) 
>>> a, b, c, d 
('q', 'w', 'e', None) 
>>> a, b, c, d = solve(iter([1, 2, 3, 4, 5]), 4) 
>>> a, b, c, d 
(1, 2, 3, 4) 
+0

È possibile rinominare la funzione in modo che assomigli a qualcosa che si utilizzerà tutto il codice, * in modo idiomatico *? – dsign

+0

Perché tagliare prima del riempimento? – Marcin

+0

@Marcin Per supportare anche gli iteratori, se l'iteratore contiene più di elementi 'n', non è necessario leggerli tutti. –

-1

si potrebbe effettivamente bisogno di creare una classe e passare line.split() in forma di elenco.

È possibile avere la sovrascrittura di classe [], ma non è consigliabile. Definire self.get_at (self, i) e restituire l'elemento all'indice, oppure None if> = len (contents).

È anche possibile definire una funzione che rileva IndexError e restituisce None per un elenco e un indice.

def get_none(none_list, i): 
    try: 
     return none_list[i] 
    except IndexError: 
     return None 
    ... or ... 
    if i >= len(none_list): return None 
    return none_list[i] 

for line in filter(fh): 
    spl = line.split() 
    ... 
    x = get_none(spl, 5) 

Non è il codice più pulito, e invece mi sento di raccomandare usando solo line.split() da solo, e la gestione della logica manualmente a seconda di ciò che si fa con le variabili in seguito e la lunghezza della lista.

+0

Questo è un modo eccessivo per questa attività. Vedi le altre risposte per soluzioni più concise. – Marcin

+0

ugh ... sì, hai ragione. – johannestaas

5

in Python 3 è possibile utilizzare questo

a, b, c, d, *_unused_ = line.split() + [None]*4 

Modifica

Per stringhe di grandi dimensioni vi consiglio di usare maxsplit -argument per Split (questo argomento funziona anche in py2.7):

a, b, c, d, *_unused_ = line.split(None, 4) + [None]*4 

Perché 5? Altrimenti il ​​4 ° elemento consisterebbe nel resto della linea.

Edit2 È 4 ... Si arresta dopo 4 spaccature, non 4 elementi

+1

Perché il voto negativo? – koffein

+0

Lo stesso è successo alla mia risposta. La mia ipotesi è la stupidità. – Marcin

+0

@Marcin E neanche nel tuo caso l'ho capito. – koffein

4

Prima di tutto, pensa al motivo per cui vuoi farlo.

Tuttavia, dato che si desidera (1) pad con None e (2) ignora variabili aggiuntive, il codice è semplice:

a,b,c,d = (line.split() + [None]*4)[:4] 

Ovviamente, il numero magico deve essere lo stesso del numero di di variabili. Questo estenderà quello che hai con il numero magico, quindi ridiscimi a quella lunghezza.

Per un iterabile arbitraria si può fare:

import itertools 

def padslice(seq,n): 
    return itertools.islice(itertools.chain(seq,itertools.repeat(None)), n) 

questo è lo stesso pad-e-slice con itertools.

+0

Downvoter: qual è il tuo problema? – Marcin

+0

+1 per python-2.7-one-liner. (Non compensativo, sul serio). Ma date un'occhiata alla vostra funzione padslice. Non restituisce una sequenza, ma penso che per decomprimere ti serva una lista o qualcosa del genere. – koffein

+1

@koffein Puoi disfare i bagagli da un generatore, quindi non ci sono problemi. – Marcin

Problemi correlati