Bagaimana cara mengubah file menjadi kamus?

95

Saya memiliki file yang terdiri dari dua kolom, yaitu,

1 a 
2 b 
3 c

Saya ingin membaca file ini ke kamus sehingga kolom 1 adalah kunci dan kolom 2 adalah nilainya, yaitu,

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

Berkasnya kecil, jadi efisiensi bukanlah masalah.

Darren J. Fitzpatrick
sumber

Jawaban:

157
d = {}
with open("file.txt") as f:
    for line in f:
       (key, val) = line.split()
       d[int(key)] = val
Vlad H.
sumber
1
Bisakah Anda menjelaskan pernyataan with?
VGE
12
withdigunakan di sini untuk menangani pembersihan file. Ketika Anda meninggalkan blok (baik hanya dengan aliran eksekusi normal atau dengan pengecualian) ada file yang akan ditutup secara otomatis. Anda dapat membaca lebih lanjut tentang pengelola konteks dengan Python di sini: effbot.org/zone/python-with-statement.htm
Vlad H
1
for line in open("file.txt"):lakukan pembersihan dengan cara yang sama. Dan jika f adalah nilai lokal, fdilepaskan saat cakupan hilang. Satu-satunya kasus di mana pernyataan ini berguna adalah untuk fungsi panjang (tidak baik untuk kualitas), atau jika Anda menggunakan variabel global.
VGE
1
@VGE, for line in open('file.txt')tidak tidak melakukan pembersihan dengan cara yang sama. Tidak semua implementasi Python sama. withmenjamin file akan ditutup ketika blok keluar. Bila forantrean sudah selesai, close boleh dipanggil. CPythonitu akan, tetapi versi seperti IronPythonmemiliki pengumpul sampah yang malas.
Mark Tolonen
2
Apakah int benar-benar diperlukan di sini? Mungkin dia ingin angka menjadi string?
GL2014
15

Ini akan meninggalkan kunci sebagai string:

with open('infile.txt') as f:
  d = dict(x.rstrip().split(None, 1) for x in f)
Ignacio Vazquez-Abrams
sumber
2
Sederhana saja dict([line.split() for line in f])sudah cukup, imo.
pengguna225312
@sukhbir: jika Anda membaca pertanyaan, Anda akan melihat bahwa bukan itu yang diinginkan op.
SilentGhost
@SilentGhost: Saya membaca bahwa OP menginginkan kunci sebagai integer, tetapi solusi Ignacio (dan juga yang saya hapus), memiliki kunci sebagai string (seperti yang ditunjukkan oleh Ignacio sendiri).
user225312
Saya bingung mengapa kita tidak perlu [] saat menyampaikan argumen dict. yaitu, dict([x.rstrip().split(None, 1) for x in f])bukan dict(x.rstrip().split(None, 1) for x in f). Bagi mereka yang berpikiran sama, yang pertama adalah ekspresi generator daripada pemahaman daftar seperti yang dijelaskan di sini: python.org/dev/peps/pep-0289(PEP-289) . Mempelajari sesuatu yang baru!
peaxol
1
@ peaxol: Kami menggunakan ekspresi generator daripada pemahaman daftar agar tidak membuat daftar perantara.
Ignacio Vazquez-Abrams
8

Anda juga dapat menggunakan pemahaman dikt seperti:

with open("infile.txt") as f:
    d = {int(k): v for line in f for (k, v) in [line.strip().split(None, 1)]}
wim
sumber
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
sumber
1
mengapa tidak partition? dan withpernyataan?
SilentGhost
@SilentGhost: Saya tidak tahu tentang partisi! tetapi mengapa lebih baik str.split dalam kasus ini? mengenai "dengan": mungkin Anda dapat mengklarifikasi hal ini untuk saya: bukankah cukup keluar dari ruang lingkup agar deskriptor file ditutup? Saya kira dalam pengecualian file utama tetap terbuka, saya akan mengubahnya.
tokland
partitionlebih cepat dan dibuat tepat untuk tujuan ini.
SilentGhost
apakah deskriptor ditutup atau tidak merupakan detail implementasi. withadalah cara sederhana untuk memastikannya.
SilentGhost
itu masih akan membutuhkan strip, kataku.
SilentGhost
3

Dengan pemahaman kamus

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

Atau dengan panda

import pandas as pd 
d = pd.read_csv("file.txt", delimiter=" ", header = None).to_dict()[0]
Samer Ayoub
sumber
Oleh panda hanya mengambil kolom pertama
Maulik Madhavi
1
@Samer Ayoub Solusi di atas (pemahaman kamus) berfungsi jika kedua kunci dan nilai adalah satu kata. Jika file teks saya memiliki data berikut, Bagaimana cara menjadikan tahun sebagai kunci dan tim pemenang sebagai nilai. 1903 Boston American 1904 No World Series 1905 New York Giants 1906 Chicago White Sox 1907 Chicago Cubs 1908 Chicago Cubs
Ridhi
1
@Ridhi Maaf atas balasan yang terlambat. Anda dapat memisahkan di ruang pertama hanya stackoverflow.com/questions/30636248/… Atau Gunakan ekspresi reguler sebagai argumen untuk pemisahan ()
Samer Ayoub
@ SamerAyoub- Terima kasih.
Ridhi
1

IMHO sedikit lebih pythonic untuk menggunakan generator (mungkin Anda membutuhkan 2.7+ untuk ini):

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

Ini juga akan memfilter baris yang tidak dimulai dengan bilangan bulat atau tidak berisi tepat dua item

Holger Bille
sumber
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
sumber
9
re? serius?
SilentGhost
Saya tidak berpikir ini adalah pendekatan terbaik.
Donovan
@ Seafoid berkata "File ini kecil, jadi efisiensi tidak menjadi masalah." split()tidak bekerja hampir tanpa suara jika format file tidak waras.
VGE
0

Jika Anda menyukai satu kalimat, coba:

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

Input FILE = Jalur ke file, SEP = Karakter pemisah Nilai-Kunci

Bukan cara yang paling elegan atau efisien untuk melakukannya, tapi tetap saja cukup menarik :)

srami
sumber
0

Berikut opsi lain ...

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
sumber
0

Opsi Sederhana

Kebanyakan metode untuk menyimpan kamus menggunakan JSON, Pickle, atau membaca baris. Asalkan Anda tidak mengedit kamus di luar Python, metode sederhana ini sudah cukup bahkan untuk kamus yang rumit. Meskipun Pickle lebih baik untuk kamus yang lebih besar.

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
sumber
0

Saya memiliki persyaratan untuk mengambil nilai dari file teks dan digunakan sebagai pasangan nilai kunci. Saya memiliki konten dalam file teks sebagai key = value, jadi saya telah menggunakan metode split dengan pemisah sebagai "=" dan menulis di bawah kode

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

Dengan menggunakan metode strip, spasi apa pun sebelum atau sesudah pemisah "=" dihapus dan Anda akan memiliki data yang diharapkan dalam format kamus

VikramReddy
sumber
Halo, selamat datang di Stack Overflow! Pendekatan Anda berbeda dari pengguna lain, tetapi dapatkah Anda mengeditnya untuk menggantikan =dengan `` untuk menjawab pertanyaan?
Prunus Persica