2011-01-26 55 views
61

Ho un file comprendente due colonne, cioè,Come convertire un file in un dizionario?

1 a 
2 b 
3 c 

desidero leggere questo file a un dizionario tale che colonna 1 è la chiave e colonna 2 è il valore, cioè,

d = {1:'a', 2:'b', 3:'c'} 

Il file è piccolo, quindi l'efficienza non è un problema.

risposta

106
d = {} 
with open("file.txt") as f: 
    for line in f: 
     (key, val) = line.split() 
     d[int(key)] = val 
+1

Puoi spiegare la frase with? – VGE

+10

'with' è usato qui per gestire la pulizia del file. Quando lasci il blocco (sia per il normale flusso di esecuzione che per un'eccezione) il file verrà automaticamente chiuso. Puoi leggere ulteriori informazioni su context-manager in Python qui: http://effbot.org/zone/python-with-statement.htm –

+1

'per la riga in apertura (" file.txt "):' effettua la pulizia allo stesso modo. E se f è un valore locale, il 'f' viene rilasciato quando l'ambito viene perso.L'unico caso in cui questa affermazione è utile è per la funzione lunga (non buona per la qualità) o se si utilizza una variabile globale. – VGE

9

Questo lascerà la chiave sotto forma di stringa:

with open('infile.txt') as f: 
    d = dict(x.rstrip().split(None, 1) for x in f) 
+1

Un semplice 'dict ([line.split() per la linea in f])' è sufficiente, imo. – user225312

+0

@sukhbir: se leggi una domanda, vedrai che non è ciò che op vuole. – SilentGhost

+0

@SilentGhost: Ho letto che l'OP vuole le chiavi come numeri interi, ma la soluzione di Ignacio (così come quella che ho cancellato), ha le chiavi come una stringa (come sottolineato da Ignacio stesso). – user225312

0
import re 

my_file = open('file.txt','r') 
d = {} 
for i in my_file: 
    g = re.search(r'(\d+)\s+(.*)', i) # glob line containing an int and a string 
    d[int(g.group(1))] = g.group(2) 
+8

're'? sul serio? – SilentGhost

+0

Non penso che questo sia l'approccio migliore. – Donovan

+2

questo non è un chiodo. – aaronasterling

3
def get_pair(line): 
    key, sep, value = line.strip().partition(" ") 
    return int(key), value 

with open("file.txt") as fd:  
    d = dict(get_pair(line) for line in fd) 
+1

perché non 'partition'? e 'with' statement? – SilentGhost

+0

@SilentGhost: non sapevo della partizione! ma perché è meglio str.split in questo caso? per quanto riguarda "with": forse puoi chiarirlo per me: non è sufficiente uscire dal campo di applicazione per la chiusura del descrittore di file? Immagino che in un'eccezione il file main rimanga aperto, lo cambierò. – tokland

+0

'partition' è più veloce ed è creato esattamente per questo scopo. – SilentGhost

6

Se la versione pitone è 2.7+, è anche possibile utilizzare un dict comprehension come:

with open('infile.txt') as f: 
    {int(k): v for line in f for (k, v) in (line.strip().split(None, 1),)} 
0

IMHO un po 'più pitonioso per usare i generatori (probabilmente hai bisogno di 2. 7+ per questo):

with open('infile.txt') as fd: 
    pairs = (line.split(None) for line in fd) 
    res = {int(pair[0]):pair[1] for pair in pairs if len(pair) == 2 and pair[0].isdigit()} 

Questo sarà anche filtrare le linee che non inizia con un intero o che non contiene esattamente due elementi

0

Se amate uno liners, provare:

d=eval('{'+re.sub('\'[\s]*?\'','\':\'',re.sub(r'([^'+input('SEP: ')+',]+)','\''+r'\1'+'\'',open(input('FILE: ')).read().rstrip('\n').replace('\n',',')))+'}') 

Input FILE = Percorso su file, SEP = Carattere separatore chiave-valore

Non è il modo più elegante o efficiente di farlo, ma piuttosto intere pungiglione comunque :)

0

Ecco un'altra opzione ...

events = {} 
for line in csv.reader(open(os.path.join(path, 'events.txt'), "rb")): 
    if line[0][0] == "#": 
     continue 
    events[line[0]] = line[1] if len(line) == 2 else line[1:] 
Problemi correlati