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.

Odpowiedzi:


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

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)

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)

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]

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


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)

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 :)


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:]

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

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


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.