Bir dosyayı sözlüğe nasıl dönüştürebilirim?


96

İki sütun içeren bir dosyam var, yani

1 a 
2 b 
3 c

Bu dosyayı, 1. sütun anahtar ve 2. sütun değer olacak şekilde bir sözlüğe okumak istiyorum.

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

Dosya küçük, bu nedenle verimlilik bir sorun değil.

Yanıtlar:


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

1
İfadesiyle açıklar mısınız?
VGE

12
withburada dosya temizliğini işlemek için kullanılır. Bloku terk ettiğinizde (sadece normal yürütme akışı ile veya bir istisna ile) dosya otomatik olarak kapatılacaktır. Python'daki bağlam yöneticileri hakkında daha fazla bilgiyi buradan okuyabilirsiniz: effbot.org/zone/python-with-statement.htm
Vlad H

1
for line in open("file.txt"):temizliği aynı şekilde yapın. Ve eğer f yerel bir değerse f, kapsam kaybolduğunda serbest bırakılır. Bu ifadenin yararlı olduğu tek durum, uzun işlev için (kalite için iyi değildir) veya bir global değişken kullanmanızdır.
VGE

1
@VGE, for line in open('file.txt')yok değil Cleanup aynı şekilde yapmak. Tüm Python uygulamaları aynı değildir. withbloktan çıkıldığında dosyanın kapatılacağını garanti eder. Ne zaman forçizgisi tamamlandığında, close olabilir çağrılabilir. CPythonolacak, ancak gibi sürümlerde IronPythontembel çöp toplayıcıları var.
Mark Tolonen

2
Burada int gerçekten gerekli mi? Belki de sayıların dizge olmasını istedi?
GL2014

15

Bu, anahtarı bir dizge olarak bırakacaktır:

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

2
Basit dict([line.split() for line in f])yeterlidir, imo.
user225312

@sukhbir: Eğer soruyu okursanız, operasyonun istediğinin bu olmadığını göreceksiniz.
SilentGhost

@SilentGhost: OP'nin anahtarları tamsayı olarak istediğini okudum, ancak Ignacio'nun çözümünde (ve sildiğim çözümde) anahtarlar dizge olarak var (Ignacio'nun kendisinin belirttiği gibi).
user225312

Dikte argümanını geçerken neden [] 'ye ihtiyacımız olmadığına şaşırmıştım. yani dict([x.rstrip().split(None, 1) for x in f])yerine dict(x.rstrip().split(None, 1) for x in f). Aynı şeyi düşünenler için, ilki, burada açıklandığı gibi liste anlama yerine bir üretici ifadesidir: python.org/dev/peps/pep-0289(PEP-289) . Yeni bir şey öğrendim!
peaxol

1
@peaxol: Ara liste oluşturmamak için liste kavrama yerine bir üretici ifadesi kullanıyoruz.
Ignacio Vazquez-Abrams

8

Aşağıdakiler gibi bir dikte anlama da kullanabilirsiniz :

with open("infile.txt") as f:
    d = {int(k): v for line in f for (k, v) in [line.strip().split(None, 1)]}

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
neden olmasın partition? ve withaçıklama?
SilentGhost

@SilentGhost: Bölmeyi bilmiyordum! ama bu durumda str.split neden daha iyidir? "with" ile ilgili olarak: belki bunu benim için netleştirebilirsiniz: dosya tanımlayıcının kapatılması için kapsam dışına çıkmak yeterli değil mi? Sanırım bir istisna olarak ana dosya açık kalıyor, onu değiştireceğim.
tokland

partitiondaha hızlıdır ve tam da bu amaç için yaratılmıştır.
SilentGhost

tanımlayıcının kapalı olup olmaması uygulamanın bir detayıdır. witholduğundan emin olmanın basit bir yoludur.
SilentGhost

yine de gerektirir strip, derdim.
SilentGhost

3

Sözlük anlayışına göre

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

Veya pandalar tarafından

import pandas as pd 
d = pd.read_csv("file.txt", delimiter=" ", header = None).to_dict()[0]

Pandalar sadece ilk sütunu alıyor
Maulik Madhavi

1
@Samer Ayoub Yukarıdaki çözüm (sözlüğü anlama), hem anahtarlar hem de değer bir kelime uzunluğundaysa işe yarar. Metin dosyamda aşağıdaki veriler varsa, yılı anahtar olarak ve kazanan takımı değer olarak nasıl yaparım? 1903 Boston Amerikalılar 1904 Dünya Serisi Yok 1905 New York Giants 1906 Chicago White Sox 1907 Chicago Cubs 1908 Chicago Cubs
Ridhi

1
@Ridhi Gecikmiş cevap için özür dilerim. İlk boşlukta yalnızca stackoverflow.com/questions/30636248/… bölebilir veya split () için bağımsız değişken olarak normal bir ifade kullanabilirsiniz
Samer Ayoub

@ SamerAyoub- Teşekkür ederim.
Ridhi

1

IMHO, jeneratörleri kullanmak için biraz daha pitonik (bunun için muhtemelen 2.7+ gerekir):

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

Bu ayrıca tamsayı ile başlamayan veya tam olarak iki öğe içermeyen satırları da filtreleyecektir.


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? ciddi anlamda?
SilentGhost

Bunun en iyi yaklaşım olduğunu düşünmüyorum.
Donovan

@Seafoid, "Dosya küçük, bu nedenle verimlilik bir sorun değil." Dedi. split()dosya biçimi mantıklı değilse neredeyse sessizce çalışmaz.
VGE

0

Bir gömlek seviyorsanız, deneyin:

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

FILE girişi = Dosyaya giden yol, SEP = Anahtar-Değer ayırıcı karakteri

Bunu yapmanın en zarif veya verimli yolu değil, ama yine de oldukça ilginç :)


0

İşte başka bir seçenek ...

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

Basit Seçenek

Bir sözlüğü saklamak için kullanılan çoğu yöntem JSON, Pickle veya satır okumayı kullanır. Sözlüğü Python dışında düzenlemediğiniz sürece, bu basit yöntem karmaşık sözlükler için bile yeterli olacaktır. Turşu daha büyük sözlükler için daha iyi olsa da.

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

Metin dosyasından değerler alıp anahtar değer çifti olarak kullanma zorunluluğum vardı. metin dosyasında anahtar = değer olarak içeriğim var, bu yüzden ayırıcıyı "=" olarak ayırma yöntemini kullandım ve aşağıdaki kodu yazdım

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

Şerit yöntemini kullanarak, "=" ayırıcısından önceki veya sonraki boşluklar kaldırılır ve beklenen verilere sözlük biçiminde sahip olursunuz


Merhaba, Stack Overflow'a hoş geldiniz! Yaklaşımınız diğer kullanıcılardan farklı, ancak onu =`` soruyu cevaplamak için '' ile değiştirecek şekilde düzenleyebilir misiniz ?
Prunus Persica
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.