Как преобразовать файл в словарь?

95

У меня есть файл, состоящий из двух столбцов, т.е.

1 a 
2 b 
3 c

Я хочу прочитать этот файл в словаре, чтобы столбец 1 был ключом, а столбец 2 - значением, т. Е.

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

Файл небольшой, поэтому эффективность не является проблемой.

Даррен Дж. Фицпатрик
источник

Ответы:

157
d = {}
with open("file.txt") as f:
    for line in f:
       (key, val) = line.split()
       d[int(key)] = val
Влад Х
источник
1
Не могли бы вы объяснить заявление с помощью?
VGE
12
withздесь используется для очистки файла. Когда вы покидаете блок (либо обычным потоком выполнения, либо в виде исключения), файл будет автоматически закрыт. Вы можете узнать больше о контекстных менеджерах в Python здесь: effbot.org/zone/python-with-statement.htm
Vlad H
1
for line in open("file.txt"):сделайте уборку таким же образом. И если f является локальным значением, fоно освобождается при потере объема. Единственный случай, когда этот оператор полезен, - это длинная функция (плохая по качеству) или если вы используете глобальную переменную.
VGE
1
@VGE, for line in open('file.txt')ничего не делать Cleanup таким же образом. Не все реализации Python одинаковы. withгарантирует, что файл будет закрыт при выходе из блока. Когда forлиния будет заполнена, close можно будет позвонить. CPythonэто будет, но в таких версиях IronPythonесть ленивые сборщики мусора.
Марк Толонен 02
2
Здесь действительно нужен int? Возможно, он хотел, чтобы числа были строками?
GL2014 08
15

Это оставит ключ в виде строки:

with open('infile.txt') as f:
  d = dict(x.rstrip().split(None, 1) for x in f)
Игнасио Васкес-Абрамс
источник
2
Достаточно простого dict([line.split() for line in f]), имо.
user225312
@sukhbir: если вы прочтете вопрос, то увидите, что op не этого хочет.
SilentGhost
@SilentGhost: Я читал, что OP хочет, чтобы ключи были целыми числами, но решение Игнасио (как и тот, который я удалил) имеет ключи в виде строки (как указал сам Игнасио).
user225312
Я был сбит с толку, почему нам не нужен [] при передаче аргумента dict. т.е. dict([x.rstrip().split(None, 1) for x in f])вместо dict(x.rstrip().split(None, 1) for x in f). Для тех, кто думает так же, первое - это выражение-генератор, а не понимание списка, как описано здесь: python.org/dev/peps/pep-0289(PEP-289) . Узнал что-то новое!
peaxol 07
1
@peaxol: мы используем выражение генератора вместо понимания списка, чтобы не создавать промежуточный список.
Игнасио Васкес-Абрамс,
8

Вы также можете использовать понимание слов, например:

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)
Tokland
источник
1
почему бы и нет partition? а withзаявление?
SilentGhost
@SilentGhost: Я не знал о разделах! но почему в этом случае лучше str.split? относительно "with": может быть, вы можете прояснить это для меня: разве недостаточно выйти за рамки, чтобы дескриптор файла был закрыт? Я предполагаю, что в исключении основной файл останется открытым, я его изменю.
tokland
partitionбыстрее и создан именно для этой цели.
SilentGhost
закрыт ли дескриптор или нет - это деталь реализации. with- простой способ убедиться в этом.
SilentGhost
stripя бы сказал, это все равно потребуется .
SilentGhost
3

По словарю

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

Или пандами

import pandas as pd 
d = pd.read_csv("file.txt", delimiter=" ", header = None).to_dict()[0]
Самер Аюб
источник
По
пандам
1
@Samer Ayoub Приведенное выше решение (понимание словаря) работает, если и ключи, и значение состоят из одного слова. Если в моем текстовом файле есть следующие данные: как сделать год ключами и команду-победителя значениями? 1903 Бостон Американцы 1904 Нет Мировой серии 1905 Нью-Йорк Джайентс 1906 Чикаго Уайт Сокс 1907 Чикаго Кабс 1908 Чикаго Кабс
Ридхи
1
@Ridhi Извините за запоздалый ответ. Вы можете либо разделить на первое пространство только stackoverflow.com/questions/30636248/…, либо использовать регулярное выражение в качестве аргумента для split ()
Самер Аюб
@ SamerAyoub- Спасибо.
Ридхи
1

IMHO немного больше pythonic для использования генераторов (возможно, для этого вам понадобится 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()}

Это также отфильтрует строки, не начинающиеся с целого числа или не содержащие ровно два элемента.

Хольгер Билле
источник
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
источник
9
re? шутки в сторону?
SilentGhost
Не думаю, что это лучший подход.
Донован
@Seafoid сказал: «Файл небольшой, поэтому эффективность не является проблемой». split()не работает почти бесшумно, если формат файла не вменяемый.
VGE
0

Если вам нравятся одинарные лайнеры, попробуйте:

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

Входной ФАЙЛ = Путь к файлу, SEP = Символ-разделитель значений ключа

Не самый элегантный и эффективный способ сделать это, но тем не менее довольно интересный :)

срами
источник
0

Вот еще вариант ...

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

Простой вариант

Большинство методов хранения словаря используют JSON, Pickle или чтение строк. Если вы не редактируете словарь вне Python, этого простого метода должно хватить даже для сложных словарей. Хотя для словарей побольше подойдет Pickle.

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

У меня было требование взять значения из текстового файла и использовать их в качестве пары значений ключа. у меня есть содержимое в текстовом файле как ключ = значение, поэтому я использовал метод разделения с разделителем как "=" и написал ниже код

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

При использовании метода полосы все пробелы до или после разделителя "=" удаляются, и вы получаете ожидаемые данные в формате словаря.

ВикрамРедди
источник
Привет, добро пожаловать в Stack Overflow! Ваш подход отличается от других пользователей, но не могли бы вы отредактировать его, заменив на =`` ответить на вопрос?
Prunus Persica