【问题标题】:Get Attribute From Text File in Python在 Python 中从文本文件中获取属性
【发布时间】:2013-03-28 19:45:51
【问题描述】:

所以我正在制作一个 Yu-Gi-Oh 数据库程序。我将所有信息都存储在一个大文本文件中。每个怪物都按以下方式分类:

|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.    

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

【问题讨论】:

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


    【解决方案1】:

    首先,这是 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])
    

    【讨论】:

    • 这太完美了!感谢您的帮助。
    【解决方案2】:

    您可以查看collections 中的namedtuple 类。您需要将每个条目设为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 或其他轻量级数据库。

    【讨论】:

      猜你喜欢
      • 2015-10-23
      • 1970-01-01
      • 1970-01-01
      • 2013-02-08
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 2020-06-30
      • 1970-01-01
      相关资源
      最近更新 更多