2012-09-21 8 views
28

sto cercando di eseguire una spaccatura stringa su un insieme di dati in qualche modo irregolare che sembra qualcosa di simile:String spaccato sulla nuova linea, scheda e un numero di spazi

\n\tName: John Smith 
\n\t Home: Anytown USA 
\n\t Phone: 555-555-555 
\n\t Other Home: Somewhere Else 
\n\t Notes: Other data 
\n\tName: Jane Smith 
\n\t Misc: Data with spaces 

vorrei convertire questo in una tupla/ditt dove più tardi mi spaccherò sul colon :, ma prima devo liberarmi di tutti gli spazi bianchi extra. Immagino che una regex sia il modo migliore ma non riesco a trovarne uno che funzioni, sotto c'è il mio tentativo.

data_string.split('\n\t *') 

risposta

61

Basta usare .strip(), rimuove tutti gli spazi per voi, tra le schede e ritorni a capo, mentre la scissione. La scissione stessa può poi essere fatto con data_string.splitlines():

[s.strip() for s in data_string.splitlines()] 

uscita:

>>> [s.strip() for s in data_string.splitlines()] 
['Name: John Smith', 'Home: Anytown USA', 'Phone: 555-555-555', 'Other Home: Somewhere Else', 'Notes: Other data', 'Name: Jane Smith', 'Misc: Data with spaces'] 

Si può anche inline la scissione in : così ora:

>>> [s.strip().split(': ') for s in data_string.splitlines()] 
[['Name', 'John Smith'], ['Home', 'Anytown USA'], ['Phone', '555-555-555'], ['Other Home', 'Somewhere Else'], ['Notes', 'Other data'], ['Name', 'Jane Smith'], ['Misc', 'Data with spaces']] 
+0

Che ha funzionato meravigliosamente, la sintassi della [List comprehension] (http://docs.python.org/tutorial/datastructures.html#list-comprehensions) non era qualcosa che avevo visto prima quindi supposi di essere io ' Dovrò leggere su di esso. – PopeJohnPaulII

+0

funziona come un fascino! eccezionale! grazie –

0

È possibile utilizzare questa

string.strip().split(":") 
5
>>> for line in s.splitlines(): 
...  line = line.strip() 
...  if not line:continue 
...  ary.append(line.split(":")) 
... 
>>> ary 
[['Name', ' John Smith'], ['Home', ' Anytown USA'], ['Misc', ' Data with spaces' 
]] 
>>> dict(ary) 
{'Home': ' Anytown USA', 'Misc': ' Data with spaces', 'Name': ' John Smith'} 
>>> 
5

È possibile prendere due piccioni con una pietra espressione regolare:

>>> r = """ 
... \n\tName: John Smith 
... \n\t Home: Anytown USA 
... \n\t Phone: 555-555-555 
... \n\t Other Home: Somewhere Else 
... \n\t Notes: Other data 
... \n\tName: Jane Smith 
... \n\t Misc: Data with spaces 
... """ 
>>> import re 
>>> print re.findall(r'(\S[^:]+):\s*(.*\S)', r) 
[('Name', 'John Smith'), ('Home', 'Anytown USA'), ('Phone', '555-555-555'), ('Other Home', 'Somewhere Else'), ('Notes', 'Other data'), ('Name', 'Jane Smith'), ('Misc', 'Data with spaces')] 
>>> 
+0

+1 per il tuo modo di dire :) – Yamaneko

+0

Abbastanza buono, ma il tuo '[\ t] *' non sta facendo nulla; il '(. +)' mangerà sempre gli spazi bianchi finali se ce n'è uno. Potresti farlo invece: '(. +?) [\ T] * $'. Il quantificatore riluttante gli permette di fermarsi presto, mentre il '$' si accerta che continui a consumare l'intera linea. –

+0

@AlanMoore: corretto, post modificato. – georg

0

Regex di non sono davvero il migliore strumento per il lavoro qui. Come altri hanno già detto, usare la combinazione di str.strip() e str.split() è la strada da percorrere. Ecco un uno di linea per farlo:

>>> data = '''\n\tName: John Smith 
... \n\t Home: Anytown USA 
... \n\t Phone: 555-555-555 
... \n\t Other Home: Somewhere Else 
... \n\t Notes: Other data 
... \n\tName: Jane Smith 
... \n\t Misc: Data with spaces''' 
>>> {line.strip().split(': ')[0]:line.split(': ')[1] for line in data.splitlines() if line.strip() != ''} 
{'Name': 'Jane Smith', 'Other Home': 'Somewhere Else', 'Notes': 'Other data', 'Misc': 'Data with spaces', 'Phone': '555-555-555', 'Home': 'Anytown USA'} 
3

Se si guarda alla the documentation per str.split:

Se sep non è specificato o è None, un algoritmo di divisione diversa si applica: corse di spazi consecutivi sono considerato come un singolo separatore e il risultato non conterrà stringhe vuote all'inizio o alla fine se la stringa ha spazi bianchi iniziali o finali. Di conseguenza, la suddivisione di una stringa vuota o di una stringa costituita da soli spazi bianchi con un separatore None restituisce [].

In altre parole, se si sta cercando di capire cosa passa per split per arrivare a '\n\tName: Jane Smith'['Name:', 'Jane', 'Smith'], basta passare nulla (o nessuno).

Questo quasi risolve il tuo intero problema. Sono rimaste due parti.

In primo luogo, hai solo due campi, il secondo dei quali può contenere spazi. Quindi, vuoi solo una divisione, non il maggior numero possibile. Quindi:

s.split(None, 1) 

Successivamente, hai ancora quei fastidiosi due punti. Ma non è necessario dividerli.Almeno data i dati che ci hai mostrato, i due punti appare sempre alla fine del primo campo, senza spazio prima e sempre spazio dopo, in modo da poter semplicemente rimuovere:

key, value = s.split(None, 1) 
key = key[:-1] 

Ci sono un milione altri modi per farlo, ovviamente; questo è solo quello che sembra più vicino a quello che stavi già provando.

Problemi correlati