Splits

Calvin (Deutschbein)

W13Wed: 20 Nov

Announcements

  • Adventure Ongoing
    • At least finish Milestone 0: TM -> ADV, to give your brain time to think
  • Advising ongoing
    • If you encounter any problem, email me immediately
    • I'll be doing triage:
      • If you don't get an email back quickly, either
        • the problem is not urgent and I'll solve it latter, or
        • I am fleeing a zamboni IRL and require thoughts & prayers stat.

Today

  • Read files.
    • Synonyms
    • Items

Adventure

  • Read files.
  • Put them in records.
  • Print out parts of records based on user input.
  • Many ways to read files:
    • The book uses a token scanner class
    • Today I will teach you to use the ".splits()" method of strings.

First Example: SmallSynonyms.txt

  • It's here.
    • Basically we want to turn this file into a dictionary.
  • It looks like this: N=NORTH S=SOUTH E=EAST W=WEST U=UP D=DOWN Q=QUIT L=LOOK I=INVENTORY CATCH=TAKE RELEASE=DROP BOTTLE=WATER

First Example: SmallSynonyms.txt

  • Basically we want to turn this file into a dictionary. N=NORTH S=SOUTH E=EAST W=WEST
  • Keys will be the strings on the left hand side (LHS) of the single equals ("=").
  • Values will be the strings on the right hand side (RHS) of the single equals ("=").
  • Basically: >>> d = {'N':'NORTH', 'S':'SOUTH'} >>> d {'N': 'NORTH', 'S': 'SOUTH'} >>> d['N'] 'NORTH'

First Example: SmallSynonyms.txt

  • We can "read" the file into a string like so: synonyms = open("SmallSynonyms.txt").read()
  • If we print out synonyms, it will give you back the text of the file.
  • Values will be the strings on the right hand side (RHS) of the single equals ("="). >>> file_text = open("SmallSynonyms.txt").read() >>> print(file_text) N=NORTH S=SOUTH ...
  • I want to turn this into a dictionary.

First Example: SmallSynonyms.txt

  • I ask:
    • What corresponds to an element of my dictionary, and
    • What separates each element?
  • I note first that key-value pairs, the elements of a dictionary, are separated by lines.
  • I can split the string on the special newline character to get a list of lines. >>> file_text 'N=NORTH\nS=SOUTH\nE=EAST\nW=WEST\n...' >>> kvps = file_text.split("\n") # key value pairs >>> kvps ['N=NORTH', 'S=SOUTH', 'E=EAST', 'W=WEST'... >>>
  • I want to turn this into a dictionary.

First Example: SmallSynonyms.txt

  • I ask:
    • What corresponds to an element of my dictionary, and
    • What separates each element?
  • I note that the keys and values are separated by single equals "="
  • I loop over the list and split each string in the list on "=". >>> kvps ['N=NORTH', 'S=SOUTH', 'E=EAST', 'W=WEST'... >>> knvs = [kvp.split("=") for kvp in kvps] # keys n values >>> knvs [['N', 'NORTH'], ['S', 'SOUTH'], ['E', 'EAST'], ['W', 'WEST'], ...
  • I want to turn this into a dictionary.

First Example: SmallSynonyms.txt

  • I ask:
    • What corresponds to an element of my dictionary, and
    • What separates each element?
  • I note that the keys and values are separated by single equals "="
  • I loop over the list and split each string in the list on "=". >>> knvs = [kvp.split("=") for kvp in kvps] # keys n values >>> knvs [['N', 'NORTH'], ['S', 'SOUTH'], ['E', 'EAST'], ['W', 'WEST'], ...
  • I want to turn this into a dictionary.

First Example: SmallSynonyms.txt

  • I ask:
    • What corresponds to an element of my dictionary, and
    • What separates each element?
  • I now have a list of lists of keys and values.
  • A list of key value pairs, perhaps.
  • I create a dictionary that loops over the list, like so: >>> knvs [['N', 'NORTH'], ['S', 'SOUTH'], ['E', 'EAST'], ['W', 'WEST'], ... >>> {key:value for key,value in knvs}
  • This draws the following ValueError: "not enough values to unpack (expected 2, got 1)"

First Example: SmallSynonyms.txt

  • I ask:
    • What corresponds to an element of my dictionary, and
    • What separates each element?
  • We debug:
    • We write out a for loop.
    • We print every value. syns = { } for knv in knvs: print("knv is", knv) key, value = knv syns[key] = value
    • We see this at the end: knv is [''] Traceback (most recent call last): ...

First Example: SmallSynonyms.txt

  • I ask:
    • What corresponds to an element of my dictionary, and
    • What separates each element?
  • We debug:
    • There was an empty line at the end of the file.
    • It had no text, so no synonym, so no key or value!
    • We use an if statement, like checking if length is equal to 2. syns = { } for knv in knvs: if len(knv) == 2: key, value = knv syns[key] = value
    • It works: >>> syns {'N': 'NORTH', ...

First Example: SmallSynonyms.txt

  • I ask:
    • What corresponds to an element of my dictionary, and
    • What separates each element?
  • We could use an "if" in the comprehension: >>> knvs [['N', 'NORTH'], ['S', 'SOUTH'], ['E', 'EAST'], ['W', 'WEST'], ... >>> {knv[0]:knv[1] for knv in knvs if len(knv) == 2} {'N': 'NORTH', 'S': 'SOUTH', ...
  • Or just clip off the last, empty line. >>> knvs [['N', 'NORTH'], ['S', 'SOUTH'], ['E', 'EAST'], ['W', 'WEST'], ... >>> {key:value for key,value in knvs[:-1]} {'N': 'NORTH', 'S': 'SOUTH', ...

First Example: SmallSynonyms.txt

  • I ask:
    • What corresponds to an element of my dictionary, and
    • What separates each element?
  • Here is a complete file to read synonyms into a dictionary: file = open("SmallSynonyms.txt").read() kvps = file.split("\n") knvs = [kvp.split("=") for kvp in kvps] syns = {key:value for key,value in knvs[:-1]} print(syns)
  • For the advanced student, this can be done in a single step: syns = {key:value for key,value in [kvp.split("=") for kvp in open("SmallSynonyms.txt").read().split("\n")][:-1]}
  • This code may help you on Milestone 5.

Today

  • Read files.
    • ✓ Synonyms
    • Items

Second Example: SmallItems.txt

  • It's here.
    • Basically we want to turn this file into a dictionary.
  • It looks like this: KEYS a set of keys InsideBuilding LAMP a brightly shining brass lamp BeneathGrate ROD a black rod with a rusty star DebrisRoom WATER a bottle of water PLAYER

Second Example: SmallItems.txt

  • Basically we want to turn this file into a dictionary?
    • Well - a dictionary of dictionaries.
    • We want to be able to place any item in any room.
    • We want items to have a known name (key) and description (value).
  • Ultimately, the way items work is: { "InsideBuilding": { "KEYS" : "a set of keys" }}
  • So we have outer keys (rooms), inner keys (items), and inner values (item descriptions).
  • This is just JSON by the way.

Second Example: SmallItems.txt

  • We note:
    • We have key-key-value entries separated by double new-lines. >>> file_text = open("SmallItems.txt").read() >>> file_text 'KEYS\na set of keys\nInsideBuilding\n\nLAMP
    • Emphasis here: \n\nLAMP
    • So we can get a list of strings, where each string corresponds to an item, like so: >>> items = file_text.split("\n\n") >>> items ['KEYS\na set of keys\nInsideBuilding', 'LAMP...

Second Example: SmallItems.txt

  • Within each item we can get outer keys, inner keys, and inner values by splitting on the newline character '\n' >>> items ['KEYS\na set of keys\nInsideBuilding', 'LAMP'... >>> >>> in_val_outs = [item.split("\n") for item in items] >>> in_val_outs [['KEYS', 'a set of keys', 'InsideBuilding'], ['LAMP', 'a brightly shining brass lamp', 'BeneathGrate'],...

Second Example: SmallItems.txt

  • Notice that this construction: [item.split("\n") for item in items]
  • Is very similar to what we did with synonyms: [kvp.split("=") for kvp in kvps]
  • Your takeaways should be:
    • Knowing a few methods helps a lot.
    • Knowing how to provide even one argument to a method solves many problems.
    • If you are systematic and take small steps, every step is easy.
    • Once you know the steps, you can make more advanced plans like "dictionary of dictionaries".

Second Example: SmallItems.txt

  • I created a dictionary where the values were the first two elements and the key was the element of index 2. >>> in_val_outs [['KEYS', 'a set of keys', 'InsideBuilding'], ['LAMP', 'a brightly shining brass lamp', 'BeneathGrate'],... >>> >>> room_contents = {ivo[2]:ivo[:2] for ivo in in_val_outs} >>> room_contents {'InsideBuilding': ['KEYS', 'a set of keys'],

Second Example: SmallItems.txt

  • Except of course, I don't want the values to be lists, I want them to be dictionaries... >>> in_val_outs [['KEYS', 'a set of keys', 'InsideBuilding'], ['LAMP', 'a brightly shining brass lamp', 'BeneathGrate'],... >>> >>> room_contents = {ivo[2]:{ivo[0]:ivo[1]} for ivo in in_val_outs} >>> room_contents {'InsideBuilding': {'KEYS': 'a set of keys'}, 'BeneathGrate': {'LAMP':...
  • With this dictionary, if you are using an AdvRoom class, you can simply look up a room (the out key) and store the contents (the inner dictionary, of item name and description) to be the contents of the room.
  • Or just store the items in AdvGame! Whatever works.

Second Example: SmallItems.txt

  • We also have to be able to print, e.g., "There is an item of some import here."
  • We need a "print_room_items()" or something. def print_room_items(room_name): contents = room_contents[room_name] for key in contents: print("There is", contents[key], "here.")
  • This may help on Milestone 3.

Second Example: SmallItems.txt

  • We can shorten the code: room_contents = {ivo[2]:{ivo[0]:ivo[1]} for ivo in [item.split("\n") for item in open("SmallItems.txt").read().split("\n\n")]} def print_room_items(room_name): [print("There is", val, "here.") for key, val in room_contents[room_name].items()]
  • This may help on Milestone 3.

Today

  • ✓ Read files.
    • Synonyms
    • Items

Announcements

  • Adventure Ongoing
    • At least finish Milestone 0: TM -> ADV, to give your brain time to think
  • Advising ongoing
    • If you encounter any problem, email me immediately
    • I'll be doing triage:
      • If you don't get an email back quickly, either
        • the problem is not urgent and I'll solve it latter, or
        • I am fleeing a zamboni IRL and require thoughts & prayers stat.