如何将文本文件提取为字典

3
我想知道如何在Python中将文本提取为字典。文本文件的格式如下所示,并以这种方式提取,使得例如地球对象成为键,其半径、周期和其他所有内容都在其键内。
RootObject: Sun

Object: Sun

Satellites: Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Ceres,Pluto,Haumea,Makemake,Eris

Radius: 20890260

Orbital Radius: 0

Object: Earth

Orbital Radius: 77098290

Period: 365.256363004

Radius: 6371000.0

Satellites: Moon

Object: Moon

Orbital Radius: 18128500

Radius: 1737000.10

Period: 27.321582

1
你想要什么样的结果?普通的字典可能不太适用,因为一些键是重复的。 - acjay
寻求将太阳系动画化为Quickdraw。 - tom smith
@tomsmith - 你能否以你希望的格式更新问题,并提供示例输入的输出?从问题中很难确定你究竟想要什么。 - Blair
输入中应该有空行吗?看起来应该有,但这可能只是格式问题...? - Petri
2
我一直看到这个作业出现...你们老师怎么了?难道他们不能像理性的教师一样给你们JSON吗?为什么要让学生解析文本文件中的 : 字符? - yurisich
3个回答

3
通过对以上方法的改进,您可以得到类似以下的内容:
def read_next_object(file):    
        obj = {}               
        for line in file:      
                if not line.strip(): continue
                line = line.strip()                        
                key, val = line.split(": ")                
                if key in obj and key == "Object": 
                        yield obj                       
                        obj = {}                              
                obj[key] = val

        yield obj              
planets = {}                   
with open( "test.txt", 'r') as f:
        for obj in read_next_object(f): 
                planets[obj["Object"]] = obj    

print planets                  

修复 RootObject 的情况,我相信这是您从所发布的示例数据中正在寻找的最终字典。它是一个行星字典,每个行星都是其信息的字典。
print planets["Sun"]["Radius"]

应该打印出值为20890260

上面的输出看起来像下面这样:

{   'Earth': {   'Object': 'Earth',
             'Orbital Radius': '77098290',
             'Period': '365.256363004',
             'Radius': '6371000.0',
             'Satellites': 'Moon'},
     'Moon': {   'Object': 'Moon',
            'Orbital Radius': '18128500',
            'Period': '27.321582',
            'Radius': '1737000.10'},
     'Sun': {   'Object': 'Sun',
           'Orbital Radius': '0',
           'Radius': '20890260',
           'RootObject': 'Sun',
           'Satellites': 'Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Ceres,Pluto,Haumea,Makemake,Eris'}}

你能否改进一下,让数字被解析成Python的十进制数,卫星则被解析成元组? - Petri
我想补充一点,但由于原帖作者没有说明他们的意图或者他们之前的尝试,他们可以将这些微不足道的补充添加到他们的代码中。我认为解决方案应该在很大程度上回答了问题。 - sean
追溯(Traceback)最近的一次调用: 文件“a4.py”,第14行,在<module>中, planets[obj]["Object"] = obj 类型错误:不可哈希类型:'dict' - tom smith
谢谢。如何将"根对象"作为主键,例如"Sun"、"Moon",并将其中的卫星(例如10个以上的卫星)拆分成列表? - tom smith
你可以在Python字符串上使用split函数将卫星拆分成列表。至于另一个,只需像行星一样查找并返回它,然后修改将行星放入主列表的第二部分,以便正确添加它。 - sean

3
nk="""
RootObject: Sun

Object: Sun
Satellites: Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Ceres,Pluto,Haumea,Makemake,Eris
Radius: 20890260
Orbital Radius: 0

Object: Earth
Orbital Radius: 77098290
Period: 365.256363004
Radius: 6371000.0
Satellites: Moon

Object: Moon
Orbital Radius: 18128500
Radius: 1737000.10
Period: 27.321582

"""

my_test_dict={}
for x in nk.splitlines():
    if ':' in x:
        if x.split(':')[0].strip()=='RootObject':
            root_obj=x.split(':')[1].strip()
        elif x.split(':')[0].strip()=='Object':
            my_test_dict[x.split(':')[1].strip()]={}
            current_dict=x.split(':')[1].strip()
            if x.split(':')[1].strip()!=root_obj:
                for x1 in my_test_dict:
                    if 'Satellites' in my_test_dict[x1]:
                        if x.split(':')[1].strip() in my_test_dict[x1]['Satellites'].split(','):
                            my_test_dict[x.split(':')[1].strip()]['RootObject']=x1
        else:
            my_test_dict[current_dict][x.split(':')[0].strip()]=x.split(':')[1].strip()

print my_test_dict

输出:

{
    'Sun':
        {
        'Satellites': 'Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Ceres,Pluto,Haumea,Makemake,Eris',
        'Orbital Radius': '0',
        'Radius': '20890260'
        },

    'Moon':
        {
        'Orbital Radius': '18128500',
        'Radius': '1737000.10',
        'Period': '27.321582',
        'RootObject': 'Earth'
         },

    'Earth':
        {
        'Satellites': 'Moon',
        'Orbital Radius': '77098290',
        'Radius': '6371000.0',
        'Period': '365.256363004',
        'RootObject': 'Sun'
        }
    }

1
请务必告诉您的老师,让他们给未来的学生提供JSON,强迫学生做这种繁琐的工作以便更深入地探讨有趣的话题是一种疯狂的做法。 - yurisich

0
假设您想要逗号分隔值作为列表的元素,请尝试以下代码:
mydict={}
with open(my_file,'r') as the_file:
    for line in the_file:
        if not line.strip(): continue # skip blank lines
        key,val=line.split(": ")
        val = val.split(",")
        mydict[key] = val if len(val) > 1 else val[0]

实际上,即使我的编辑也不足够,因为存在冲突。需要更多来自 OP 的信息。 - acjay
是的,不幸的是,尽管按照它所说的去做,这个答案并没有真正回答问题...而且在此过程中还会丢失数据。 - Petri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接