Làm thế nào để chuyển đổi một tập tin thành một từ điển?


94

Tôi có một tệp bao gồm hai cột, tức là,

1 a 
2 b 
3 c

Tôi muốn đọc tệp này vào từ điển sao cho cột 1 là khóa và cột 2 là giá trị, tức là

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

Tệp nhỏ, vì vậy hiệu quả không phải là một vấn đề.

Câu trả lời:


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

1
Bạn có thể giải thích tuyên bố với?
VGE

12
withđược sử dụng ở đây để xử lý việc dọn dẹp tệp. Khi bạn rời khỏi khối (chỉ bằng luồng thực thi thông thường hoặc theo một ngoại lệ), tệp sẽ tự động bị đóng. Bạn có thể đọc thêm về bối cảnh các nhà quản lý bằng Python ở đây: effbot.org/zone/python-with-statement.htm
Vlad H

1
for line in open("file.txt"):làm sạch theo cách tương tự. Và nếu f là một giá trị cục bộ thì fsẽ được giải phóng khi phạm vi bị mất. Trường hợp duy nhất mà câu lệnh này hữu ích là cho hàm dài (không tốt cho chất lượng) hoặc nếu bạn sử dụng một biến toàn cục.
VGE

1
@VGE, for line in open('file.txt')không không làm dọn dẹp cùng một cách. Không phải tất cả các triển khai Python đều giống nhau. withđảm bảo tệp sẽ được đóng khi khối được thoát. Khi fordòng hoàn tất, close có thể được gọi. CPythonnó sẽ làm được, nhưng các phiên bản như IronPythoncó bộ thu gom rác lười biếng.
Mark Tolonen

2
Int có thực sự cần thiết ở đây không? Có lẽ anh ta muốn những con số là chuỗi?
GL2014

15

Điều này sẽ để lại khóa dưới dạng một chuỗi:

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

2
Đơn giản dict([line.split() for line in f])là đủ, imo.
user225312

@sukhbir: nếu bạn đọc câu hỏi, bạn sẽ thấy đó không phải là điều op muốn.
SilentGhost

@SilentGhost: Tôi đọc rằng OP muốn các khóa là số nguyên, nhưng giải pháp của Ignacio (cũng như giải pháp tôi đã xóa), có các khóa là một chuỗi (như chính Ignacio đã chỉ ra).
user225312

Tôi đã nhầm lẫn tại sao chúng ta không cần [] khi chuyển đối số dict. tức là dict([x.rstrip().split(None, 1) for x in f])thay vì dict(x.rstrip().split(None, 1) for x in f). Đối với những người nghĩ cùng một điều, trước đây là một biểu thức trình tạo thay vì hiểu danh sách như được giải thích ở đây: python.org/dev/peps/pep-0289(PEP-289) . Học được điều gì đó mới!
peaxol

1
@peaxol: Chúng tôi sử dụng biểu thức trình tạo thay vì hiểu danh sách để không tạo danh sách trung gian.
Ignacio Vazquez-Abrams

7

Nếu phiên bản python của bạn là 2.7+, bạn cũng có thể sử dụng cách đọc chính tả như:

with open('infile.txt') as f:
  {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
tại sao không partition? và withtuyên bố?
SilentGhost

@SilentGhost: Tôi không biết về phân vùng! nhưng tại sao nó tốt hơn để str.split trong trường hợp này? liên quan đến "with": có thể bạn có thể làm rõ điều này cho tôi: nó không đủ để vượt ra khỏi phạm vi để đóng bộ mô tả tệp? Tôi đoán trong một ngoại lệ, tệp chính vẫn mở, tôi sẽ thay đổi nó.
tokland

partitionnhanh hơn và được tạo cho chính xác mục đích này.
SilentGhost

việc bộ mô tả có được đóng hay không là một chi tiết của việc thực hiện. withlà một cách đơn giản để đảm bảo rằng nó là như vậy.
SilentGhost

nó vẫn sẽ yêu cầu strip, tôi sẽ nói.
SilentGhost

3

Bằng cách hiểu từ điển

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

Hoặc bởi gấu trúc

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

Bởi gấu trúc chỉ chiếm cột đầu tiên
Maulik Madhavi

1
@Samer Ayoub Giải pháp trên (đọc hiểu từ điển) hoạt động nếu cả khóa và giá trị đều dài một từ. Nếu tệp văn bản của tôi có dữ liệu sau. Làm cách nào để tôi lập năm là khóa và đội chiến thắng làm giá trị. 1903 Boston American 1904 No World Series 1905 New York Giants 1906 Chicago White Sox 1907 Chicago Cubs 1908 Chicago Cubs
Ridhi

1
@Ridhi Xin lỗi vì trả lời muộn. Bạn có thể tách trên không gian đầu tiên chỉ stackoverflow.com/questions/30636248/… Hoặc Sử dụng biểu thức chính quy làm đối số cho split ()
Samer Ayoub

@ SamerAyoub- Cảm ơn bạn.
Ridhi

1

IMHO một chút khó khăn hơn để sử dụng máy phát điện (có thể bạn cần 2.7+ cho việc này):

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

Điều này cũng sẽ lọc ra các dòng không bắt đầu bằng số nguyên hoặc không chứa chính xác hai mục


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? nghiêm túc?
SilentGhost

Tôi không nghĩ đây là cách tiếp cận tốt nhất.
Donovan

@Seafoid cho biết "Tệp nhỏ nên hiệu quả không phải là vấn đề." split()không hoạt động gần như im lặng nếu định dạng tệp không tốt.
VGE

0

Nếu bạn yêu thích một lớp lót, hãy thử:

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

Đầu vào FILE = Đường dẫn đến tệp, SEP = Ký tự phân tách Khóa-Giá trị

Không phải là cách làm thanh lịch hay hiệu quả nhất, nhưng vẫn khá thú vị :)


0

Đây là một tùy chọn khác ...

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

Lựa chọn đơn giản

Hầu hết các phương pháp lưu trữ từ điển sử dụng JSON, Pickle hoặc đọc dòng. Với điều kiện bạn không chỉnh sửa từ điển bên ngoài Python, phương pháp đơn giản này sẽ đủ cho các từ điển phức tạp. Mặc dù Pickle sẽ tốt hơn cho các từ điển lớn hơn.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.