在Python中从文本文件中获取属性

时间:2013-03-28 19:45:51

标签: python text python-2.7 python-3.x

所以我正在制作一个游戏王数据库程序。我将所有信息存储在一个大文本文件中。每个怪物都按照以下方式进行了分类:

|Name|NUM 1|DESC 1|TYPE|LOCATION|STARS|ATK|DEF|DESCRIPTION

这是一个实际的例子:

|A Feather of the Phoenix|37;29;18|FET;YSDS;CP03|Spell Card}Spell||||Discard 1 card. Select from your Graveyard and return it to the top of your Deck.|

所以我创建了一个程序,按名称搜索这个大文本文件,它返回文本文件中没有“|”的信息。这是:

    with open('TEXT.txt') as fd:
         input=[x.strip('|').split('|') for x in fd.readlines()]
         to_search={x[0]:x for x in input}
         print('\n'.join(to_search[name]))

现在我正在尝试编辑我的程序,以便我可以搜索怪物的名称并选择我想要显示的属性。所以它看起来像

A Feather of the Phoenix 
Description:
Discard 1 card. Select from your Graveyard and return it to the top of your Deck.    

关于我如何做到这一点的任何线索?

2 个答案:

答案 0 :(得分:5)

首先,这是CSV的变体方言,可以使用csv模块进行解析,而不是尝试手动执行。例如:

with open('TEXT.txt') as fd:
    rows = csv.reader(fd, delimiter='|')
    to_search = {row[1]:row for row in rows}
    print('\n'.join(to_search[name]))

您可能也更喜欢使用DictReader,因此每行都是dict(在标题行中键入名称,如果没有,则手动指定列名称):

with open('TEXT.txt') as fd:
    rows = csv.DictReader(fd, delimiter='|')
    to_search = {row['Name']:row for row in rows}
    print('\n'.join(to_search[name]))

然后,选择一个特定的属性:

with open('TEXT.txt') as fd:
    rows = csv.DictReader(fd, delimiter='|')
    to_search = {row['Name']:row for row in rows}
    print(to_search[name][attribute])

但是......我不确定这是一个好的设计。你真的想为每次查找重新读取整个文件吗?我认为将它一次性读入内存更有意义,将其转换为可以重复使用的通用结构。事实上,你几乎有这样的结构:

with open('TEXT.txt') as fd:
    monsters = list(csv.DictReader(fd, delimiter='|'))
monsters_by_name = {monster['Name']: monster for monster in monsters}

然后,如果需要,您可以构建其他索引,例如按位置等的多个怪物地图。


所有这一切,您的原始代码几乎可以处理您想要的。 to_search[name]list。如果您只是从属性名称到索引构建映射,则可以执行以下操作:

attributes = ['Name', 'NUM 1', 'DESC 1', 'TYPE', 'LOCATION', 'STARS', 'ATK', 'DEF', 'DESCRIPTION']
attributes_by_name = {value: idx for idx, value in enumerate(attributes)}
# ...
with open('TEXT.txt') as fd:
     input=[x.strip('|').split('|') for x in fd.readlines()]
     to_search={x[0]:x for x in input}
     attribute_index = attributes_by_name[attributes]
     print(to_search[name][attribute_index])

答案 1 :(得分:0)

您可以查看namedtuple中的collections课程。您需要将每个条目设为namedtuple,并将字段作为属性。 namedtuple可能看起来像:

Card = namedtuple('Card', 'name, number, description, whatever_else')

如集合文档中所示,namedtuple和csv可以很好地协同工作:

import csv
for card in map(Card._make, csv.reader(open("cards", "rb"))):
    print card.name, card.description # format however you want here

搜索的机制可能非常复杂。例如,如果您希望围绕完全匹配建立一个非常快速的搜索,您可以为您感兴趣的每个属性构建一个字典:

name_map = {card.name: card for card in all_cards}
search_result = name_map[name_you_searched_for]

您还可以进行startswith搜索:

possibles = [card for card in all_cards if card.name.startswith(search_string)]
# here you need to decide what to do with these possibles, in this example, I'm just snagging the first one, and I'm not handling the possibility that you don't find one, you should.
search_result = possibles[0]

我建议不要尝试搜索文件本身。这是一种非常复杂的搜索,通常由数据库系统来实现这种功能。如果需要这样做,请考虑将应用程序切换到sqlite或其他轻量级数据库。