Jak przekonwertować plik do słownika?

95

Mam plik zawierający dwie kolumny, tj.

1 a 
2 b 
3 c

Chciałbym czytać ten plik do słownika w taki sposób, że kolumna 1 to klucz, a kolumna 2 to wartość, tj.

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

Plik jest mały, więc wydajność nie jest problemem.

Darren J. Fitzpatrick
źródło

Odpowiedzi:

158
d = {}
with open("file.txt") as f:
    for line in f:
       (key, val) = line.split()
       d[int(key)] = val
Vlad H.
źródło
1
Czy mógłbyś wyjaśnić za pomocą oświadczenia?
VGE
12
withjest tutaj używany do obsługi czyszczenia pliku. Kiedy opuścisz blok (albo przez zwykły przepływ wykonywania, albo w drodze wyjątku), plik zostanie automatycznie zamknięty. Możesz przeczytać więcej o menedżerach kontekstu w Pythonie tutaj: effbot.org/zone/python-with-statement.htm
Vlad H
1
for line in open("file.txt"):czyścić w ten sam sposób. A jeśli f jest wartością lokalną, fjest zwalniana, gdy zakres zostanie utracony. Jedynym przypadkiem, w którym ta instrukcja jest przydatna, jest długa funkcja (nie dobra ze względu na jakość) lub jeśli używasz zmiennej globalnej.
VGE
1
@VGE, for line in open('file.txt')czy nie zrobić Cleanup w ten sam sposób. Nie wszystkie implementacje Pythona są takie same. withgwarantuje, że plik zostanie zamknięty po wyjściu z bloku. Gdy forlinia jest kompletna, close można wywołać. CPythonbędzie, ale wersje takie jak IronPythonmają leniwe zbieracze śmieci.
Mark Tolonen
2
Czy jest to naprawdę konieczne? Może chciał, aby liczby były łańcuchami?
GL2014
15

To pozostawi klucz jako ciąg:

with open('infile.txt') as f:
  d = dict(x.rstrip().split(None, 1) for x in f)
Ignacio Vazquez-Abrams
źródło
2
Prosty dict([line.split() for line in f])wystarczy, imo.
user225312
@sukhbir: jeśli przeczytasz pytanie, zobaczysz, że nie tego chce op.
SilentGhost
@SilentGhost: Czytałem, że OP chce kluczy jako liczb całkowitych, ale rozwiązanie Ignacio (podobnie jak to, które usunąłem) ma klucze jako ciąg (jak wskazał sam Ignacio).
user225312
Byłem zdezorientowany, dlaczego nie potrzebujemy [] podczas przekazywania argumentu dyktowania. tj. dict([x.rstrip().split(None, 1) for x in f])zamiast dict(x.rstrip().split(None, 1) for x in f). Dla tych, którzy myślą to samo, pierwsze jest wyrażeniem generatora zamiast rozumienia listy, jak wyjaśniono tutaj: python.org/dev/peps/pep-0289(PEP-289) . Nauczyłem się czegoś nowego!
peaxol
1
@peaxol: Używamy wyrażenia generatora zamiast rozumienia listy, aby nie tworzyć listy pośredniej.
Ignacio Vazquez-Abrams
5
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)
tokland
źródło
1
dlaczego nie partition? i withoświadczenie?
SilentGhost
@SilentGhost: Nie wiedziałem o partycji! ale dlaczego w tym przypadku lepiej jest str.split? w odniesieniu do „z”: może mógłbyś mi to wyjaśnić: czy nie wystarczy wyjść poza zakres, aby zamknąć deskryptor pliku? Myślę, że w wyjątku główny plik pozostaje otwarty, zmienię go.
tokland
partitionjest szybszy i jest stworzony właśnie do tego celu.
SilentGhost
to, czy deskryptor jest zamknięty, czy nie, jest szczegółem implementacji. withto prosty sposób na zapewnienie, że tak jest.
SilentGhost
nadal by to wymagało strip, powiedziałbym.
SilentGhost
3

Rozumienie ze słownika

d = { line.split()[0] : line.split()[1] for line in open("file.txt") }

Albo przez pandy

import pandas as pd 
d = pd.read_csv("file.txt", delimiter=" ", header = None).to_dict()[0]
Samer Ayoub
źródło
Przez pandy zajmuje tylko pierwszą kolumnę
Maulik Madhavi
1
@Samer Ayoub Powyższe rozwiązanie (rozumienie słownikowe) działa, jeśli zarówno klucze, jak i wartość mają długość jednego słowa. Jeśli mój plik tekstowy zawiera następujące dane: jak ustawić rok jako klucze, a zwycięską drużynę jako wartości. 1903 Boston Americans 1904 No World Series 1905 New York Giants 1906 Chicago White Sox 1907 Chicago Cubs 1908 Chicago Cubs
Ridhi
1
@Ridhi Przepraszamy za spóźnioną odpowiedź. Możesz podzielić tylko na pierwszą spację stackoverflow.com/questions/30636248/ ... Lub Użyj wyrażenia regularnego jako argumentu dla funkcji split ()
Samer Ayoub
@ SamerAyoub- Dziękuję.
Ridhi
1

IMHO trochę bardziej pythonowe, aby używać generatorów (prawdopodobnie potrzebujesz do tego 2.7+):

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()}

Spowoduje to również odfiltrowanie wierszy, które nie zaczynają się od liczby całkowitej lub nie zawierają dokładnie dwóch elementów

Holger Bille
źródło
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)
VGE
źródło
9
re? poważnie?
SilentGhost
Nie sądzę, żeby to było najlepsze podejście.
Donovan,
@Seafoid powiedział: „Plik jest mały, więc wydajność nie jest problemem”. split()nie działa prawie bezgłośnie, jeśli format pliku nie jest rozsądny.
VGE
0

Jeśli kochasz one wkładki, wypróbuj:

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

Plik wejściowy FILE = ścieżka do pliku, SEP = znak separatora klucz-wartość

Nie jest to najbardziej elegancki i skuteczny sposób, ale dość interesujący :)

srami
źródło
0

Oto inna opcja ...

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:]
Robel Robel Lingstuyl
źródło
0

Prosta opcja

Większość metod przechowywania słownika używa formatu JSON, Pickle lub czytania linii. Zakładając, że nie edytujesz słownika poza Pythonem, ta prosta metoda powinna wystarczyć nawet w przypadku złożonych słowników. Chociaż Pickle będzie lepsza dla większych słowników.

x = {1:'a', 2:'b', 3:'c'}
f = 'file.txt'
print(x, file=open(f,'w'))    # file.txt >>> {1:'a', 2:'b', 3:'c'}
y = eval(open(f,'r').read())
print(x==y)                   # >>> True
A. West
źródło
0

Miałem wymóg, aby pobrać wartości z pliku tekstowego i użyć ich jako pary klucz-wartość. Mam zawartość w pliku tekstowym jako klucz = wartość, więc użyłem metody podziału z separatorem jako "=" i napisałem poniższy kod

d = {}
file = open("filename.txt")
for x in file:
    f = x.split("=")
    d.update({f[0].strip(): f[1].strip()})

Używając metody strip, wszelkie spacje przed lub po separatorze "=" są usuwane, a oczekiwane dane będą miały format słownikowy

VikramReddy
źródło
Cześć, witamy w Stack Overflow! Twoje podejście różni się od innych użytkowników, ale czy możesz je edytować, aby zastąpić =znak ``, aby odpowiedzieć na pytanie?
Prunus Persica