1

So I'm making a Yu-Gi-Oh database program. I have all the information stored in a large text file. Each monster is chategorized in the following way:

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

Here's an actual example:

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

So I made a program that searches this large text file by name and it returns the information from the text file without the '|'. Here it is:

    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]))

Now I'm trying to edit my program so I can search for the name of the monster and choose which attribute I want to display. So it'd appear like

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

Any clues as to how I can do this?

2 Answers 2

5

First, this is a variant dialect of CSV, and can be parsed with the csv module instead of trying to do it manually. For example:

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]))

You might also prefer to use DictReader, so each row is a dict (keyed off the names in the header row, or manually-specified column names if you don't have one):

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]))

Then, to select a specific attribute:

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])

However… I'm not sure this is a good design in the first place. Do you really want to re-read the entire file for each lookup? I think it makes more sense to read it into memory once, into a general-purpose structure that you can use repeatedly. And in fact, you've almost got such a structure:

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

Then you can build additional indexes, like a multi-map of monsters by location, etc., if you need them.


All this being said, your original code can almost handle what you want already. to_search[name] is a list. If you just build a map from attribute names to indices, you can do this:

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])
Sign up to request clarification or add additional context in comments.

Comments

0

You could look at the namedtuple class in collections. You will want to make each entry a namedtuple with your fields as attributes. The namedtuple might look like:

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

As shown in the collections documentation, namedtuple and csv work well together:

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

The mechanics around search can be very complicated. For example, if you want a really fast search built around an exact match, you could build a dictionary for each attribute you're interested in:

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

You could also do a startswith search:

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]

I recommend against trying to search the file itself. This is an extremely complex kind of search to do and is typically left up to database systems to implement this kind of functionality. If you need to do this, consider switching the application to sqlite or another lightweight database.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.