จะแปลงไฟล์เป็นพจนานุกรมได้อย่างไร?


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')ไม่ได้ทำการล้างข้อมูลในลักษณะเดียวกัน การใช้งาน Python ทั้งหมดไม่เหมือนกัน withรับประกันว่าไฟล์จะถูกปิดเมื่อออกจากบล็อก เมื่อforสายสมบูรณ์close อาจเรียก. CPythonมันจะ แต่รุ่นเหมือนIronPythonมีคนเก็บขยะขี้เกียจ
Mark Tolonen

2
int จำเป็นจริงๆหรือ บางทีเขาอาจต้องการให้ตัวเลขเป็นสตริง?
GL2014

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])ก็เพียงพอแล้ว imo
user225312

@sukhbir: ถ้าคุณอ่านคำถามคุณจะเห็นว่านั่นไม่ใช่สิ่งที่ op ต้องการ
SilentGhost

@SilentGhost: ฉันอ่านว่า OP ต้องการคีย์เป็นจำนวนเต็ม แต่โซลูชันของ Ignacio (เช่นเดียวกับที่ฉันลบไปแล้ว) มีคีย์เป็นสตริง (ตามที่ Ignacio ชี้ให้เห็น)
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

1
@peaxol: เราใช้นิพจน์ตัวสร้างแทนการเข้าใจรายการเพื่อที่จะไม่สร้างรายการกลาง
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
ทำไมไม่partition? และwithคำสั่ง?
SilentGhost

@SilentGhost: ฉันไม่รู้เรื่องพาร์ทิชัน! แต่ทำไม str.split ถึงดีกว่าในกรณีนี้? เกี่ยวกับ "กับ": บางทีคุณอาจชี้แจงเรื่องนี้ให้ฉันได้: มันไม่เพียงพอที่จะออกนอกขอบเขตเพื่อให้ตัวอธิบายไฟล์ถูกปิดหรือไม่? ฉันเดาว่าในกรณีที่ไฟล์หลักยังคงเปิดอยู่ฉันจะเปลี่ยนมัน
tokland

partitionเร็วกว่าและถูกสร้างขึ้นเพื่อจุดประสงค์นี้
SilentGhost

ไม่ว่า descriptor จะปิดหรือไม่เป็นรายละเอียดของการนำไปใช้งาน 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]

โดยแพนด้าใช้เวลาคอลัมน์แรกเท่านั้น
Maulik Madhavi

1
@Samer Ayoub วิธีแก้ปัญหาข้างต้น (ความเข้าใจในพจนานุกรม) ใช้งานได้ถ้าทั้งคีย์และค่ามีความยาวคำเดียว หากไฟล์ข้อความของฉันมีข้อมูลต่อไปนี้ฉันจะสร้างปีเป็นคีย์และทีมที่ชนะเป็นค่าได้อย่างไร 1903 Boston American 1904 No World Series 1905 New York Giants 1906 Chicago White Sox 1907 Chicago Cubs 1908 Chicago Cubs
Ridhi

1
@Ridhi ขออภัยสำหรับการตอบกลับล่าช้า คุณสามารถแบ่งในช่องว่างแรกเท่านั้น stackoverflow.com/questions/30636248/… หรือใช้นิพจน์ทั่วไปเป็นอาร์กิวเมนต์สำหรับการแยก ()
Samer Ayoub

@ SamerAyoub- ขอบคุณครับ
Ridhi

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)

9
reเหรอ? อย่างจริงจัง?
SilentGhost

ฉันไม่คิดว่านี่เป็นแนวทางที่ดีที่สุด
Donovan

@ ซีฟอยด์กล่าวว่า "ไฟล์มีขนาดเล็กประสิทธิภาพจึงไม่ใช่ปัญหา" 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

ฉันมีความต้องการที่จะรับค่าจากไฟล์ข้อความและใช้เป็นคู่ค่าคีย์ ฉันมีเนื้อหาในไฟล์ข้อความเป็น key = value ดังนั้นฉันจึงใช้วิธีการแยกโดยมีตัวคั่นเป็น "=" และเขียนโค้ดด้านล่าง

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

โดยใช้วิธีแถบช่องว่างก่อนหรือหลังตัวคั่น "=" จะถูกลบออกและคุณจะมีข้อมูลที่คาดไว้ในรูปแบบพจนานุกรม


สวัสดียินดีต้อนรับสู่ Stack Overflow! แนวทางของคุณแตกต่างจากผู้ใช้รายอื่น แต่คุณสามารถแก้ไขเพื่อแทนที่=ด้วย `เพื่อตอบคำถามได้หรือไม่?
Prunus Persica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.