Python Dictionary's

Discussion in 'Mac Programming' started by larswik, Apr 18, 2009.

  1. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    While I am learning Python I work on separate (outside the book) projects to improve my skills. A friend has had some fun sending text that has been converted to binary and the other person converting it back to text again to read. I thought this would be a fun project to try out.

    I decided to use Dictionary's for the (Key : Value) for all the letters and symbols on the keyboard. ie. list = {"a" : "01000001"}

    When I use code like this
    Code:
    if pick == "A":
        for letters in word:
            print list[letters],
    
    it prints out the letters of the word in in binary code which is fine. The question that I am asking that I don't know is, How do I do the revers of that? Instead of calling the KEY and getting the VALUE which I have done. I want to call the VALUE and get the KEY? This will then allow me to put the binary to letters so I can create words.

    Thanks!

    -Lars
     
  2. larkost macrumors 6502a

    Joined:
    Oct 13, 2007
    #2
    The simple way of doing this would be to build a second dictionary with they keys and values swapped.
     
  3. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #3
    larkost's suggestion seems best, otherwise you'll have to loop over items or values each time. From:
    http://docs.python.org/library/stdtypes.html#dict.items

    Code:
    revlist = zip(list.values(), list.keys())
    This should get you a dict w/ list's values as the keys, and keys as the values. In this case it is not a worry, but you have to be sure your values are unique for this to work.

    -Lee
     
  4. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #4
    It's funny, I got the 2 responses I was looking for. I thought about doing a second dictionary and reversing them like you suggested. The other answer was the one I was worried about. Using some code that I have not come across yet in the book. I am not familiar with the 'ZIP' function yet? I don't know if you can call that a function. It would be a lot easier to use that bt I should go with what I know from the book so far.

    Thanks much!

    -Lars
     
  5. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #5
    If you don't want to worry about zip yet you can just loop over list's keys, items, etc and build the new dict that way, or you can just manually build the second dictionary. You'll end up with the same thing, zip is just the shortest once you have a dictionary you want to reverse.

    -Lee

    P.S. I don't know python, I was just reading the docs and that example of zip seemed easier than my initial thought of looping over items, etc.
     
  6. eddietr macrumors 6502a

    Joined:
    Oct 29, 2006
    Location:
    Virginia
    #6
    So just one quick note, to create a "reverse dictionary", you need to wrap what Lee had written in a dict().

    So it actually would be:

    Code:
    myReverseDictionary = dict(zip(myDictionary.values(),myDictionary.keys()))
    
    And, btw Lars, using a variable called "list" to refer to a dictionary is bad Python karma. :)
     
  7. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #7
    eddietr - Thanks for the 'list' note. I did see it but I didn't put 2 and 2 together until you mentioned it.

    thanks lee1210 -I will wait on the zip till I read it in the book. I don't want to get a head of myself.

    I decided not to go past the book and use the ZIP method, so I created a second dictionary and now I have a new problem. The code will look long, sorry. Since the 'num' variables are getting a "1" or "0" I assigned a "3" to the 8 'num's. By joining the strings together I got a string that the 'List2' would see and return a letter (the VALUE of the KEY). It worked great until I tried to get it to do 2 letters using something like this '0100000101000010', that should have printed the letters "a" and "b". From my understanding using the 'IN' operator it counts the letters in the string. I assign those 8 letters to the 8 different 'num' variables. Then add them together into 1 new variable, in this case called "letter". I can then use the 'letter' variable in the 'list2[letter] to get the value from the key. After that I change all the 'num' back to "3" it starts over. I thought the 'IN' operator would continue counting the next set of 8 string characters 9-16 and assign them to the num all over again, but I am getting a strange result that I can't explain? It's kicking out a totally different letter then expected.

    O by the way, I use the 'count' variable just run the while loop.

    Code:
    count = 2
    letter = ""
    num1 = "3"
    num2 = "3"
    num3 = "3"
    num4 = "3"
    num5 = "3"
    num6 = "3"
    num7 = "3"
    num8 = "3"
    
    list2 = {"01000001" : "a",
             "01000010" : "b",
             "01000011" : "c",
             "01000100" : "d",
             "01000101" : "e",
             "01000110" : "f",
             "01000111" : "g",
             "01001000" : "h",
             "01001001" : "i",
             "01001010" : "j",
             "01001011" : "k"}
    
    binary = raw_input("Enter 8 numbers to fined the letter: ")
    while count != 0:
        for number in binary:
            if num1 == "3":
                num1 = number
            elif num2 == "3":
                num2 = number
            elif num3 == "3":
                num3 = number
            elif num4 == "3":
                num4 = number
            elif num5 == "3":
                num5 = number
            elif num6 == "3":
                num6 = number
            elif num7 == "3":
                num7 = number
            elif num8 == "3":
                num8 = number
        letter = num1 + num2 + num3 + num4 + num5 + num6 + num7 + num8
        print list2[letter]
        print letter
        count -=1
        num1 = "3"
        num2 = "3"
        num4 = "3"
        num5 = "3"
        num6 = "3"
        num7 = "3"
        num8 = "3"
        letter = ""
    
    reading the book is great but it is nice to have you folks as the teacher to answer questions when I get lost.

    -Lars
     
  8. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #8
    Your approach is not quite right here.

    For one, at the end of your while loop you don't set num3 back to "3", so your for loop gets "off" since it depends on this, so you get a different value the second time through the loop, even though binary has not changed.

    For two, the second time through the while, binary is the same as the first time through... you'll get the same value for letter (which will be the first 8 characters of binary) both times through.

    Third, The means of building letter is pretty strange/involved. I don't know what the book as covered so far, but if you wanted to just accept a single character at a time, you could just do this (no error checking in this example):
    Code:
    binToChar = {"01000001" : "a",
             "01000010" : "b",
             "01000011" : "c",
             "01000100" : "d",
             "01000101" : "e",
             "01000110" : "f",
             "01000111" : "g",
             "01001000" : "h",
             "01001001" : "i",
             "01001010" : "j",
             "01001011" : "k"}
    
    binary = raw_input("Enter 8 numbers to find the letter: ")
    print "The letter is: " + binToChar[binary]
    
    If you want to accept more than one character in binary at a time, you'll need to figure out how many characters are present, and grab 8 characters at a time and convert them. Again, I don't know how far you are (i.e. if sequence slicing has been covered, the in statement, etc.), but that would look something like this:
    Code:
    binToChar = {"01000001" : "a",
             "01000010" : "b",
             "01000011" : "c",
             "01000100" : "d",
             "01000101" : "e",
             "01000110" : "f",
             "01000111" : "g",
             "01001000" : "h",
             "01001001" : "i",
             "01001010" : "j",
             "01001011" : "k"}
    
    binary = raw_input("Enter bits in sets of 8 to get a series of characters: ")
    if len(binary)%8 != 0:
      print "Invalid number of bits!"
    else:
      startpos=0
      while startpos < len(binary):
        singleLetter = binary[startpos:startpos+8]
        if singleLetter in binToChar.keys():
          print binToChar[singleLetter]
        else:
          print singleLetter + " is not a valid binary representation of an ASCII character"
        startpos+=8
    
    Instead of using "in" in an if, it could be in a for if you wanted to do the search that way. As for the sequence slicing... I'm not sure how I'd approach that otherwise. I suppose you could use your num1-num8 idea, and loop over the characters in binary, keeping a count, then print each 8, and start again. Maybe something like:
    Code:
    binToChar = {"01000001" : "a",
             "01000010" : "b",
             "01000011" : "c",
             "01000100" : "d",
             "01000101" : "e",
             "01000110" : "f",
             "01000111" : "g",
             "01001000" : "h",
             "01001001" : "i",
             "01001010" : "j",
             "01001011" : "k"}
    
    binary = raw_input("Enter bits in sets of 8 to get a series of characters: ")
    if len(binary)%8 != 0:
      print "Invalid number of bits!"
    else:
      curPos = 0
      for singleChar in binary:
        whichPos = curPos % 8
        curPos+=1
        if(whichPos == 0):
          num0=singleChar
        elif (whichPos == 1):
          num1=singleChar
        elif (whichPos == 2):
          num2=singleChar
        elif (whichPos == 3):
          num3=singleChar
        elif (whichPos == 4):
          num4=singleChar
        elif (whichPos == 5):
          num5=singleChar
        elif (whichPos == 6):
          num6=singleChar
        elif (whichPos == 7):
          num7=singleChar
          singleLetter = num0 + num1 + num2 + num3 + num4 + num5 + num6 + num7
    
          found=False
          for key in binToChar.keys():
            if singleLetter == key:
              found=True
          if found:
            print binToChar[singleLetter]
          else:
            print singleLetter + " is not a valid binary representation of an ASCII character"
    
    This doesn't use anything you didn't use except % and .keys(). I wouldn't normally want to do something like that, but I didn't know if you had covered generating your own arrays, etc.

    One of the problems with "working through" learning something and trying to implement example code is that you are forced to do things in an unnatural way. It's important to learn how the basics work first, but in practice some things would never be done because there are much better constructs to handle them.

    -Lee
     
  9. eddietr macrumors 6502a

    Joined:
    Oct 29, 2006
    Location:
    Virginia
    #9
    Lars, which book are you using?

    In the Python class I teach, I cover list and slices of lists pretty early (day 1), since lists are really a core concept in the "Python way" of doing things.

    If you've covered slices, then this problem is very easy to solve.
     
  10. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #10
    Lee1210- Wow thanks for the effort you put into your example. I looked over the my code for an hour yesterday and I can't believe that I over looked the 'num3' rest that I did. I think I will stick to your second example for my work flow for right now.

    eddietr - I am reading the book 'Python Programming Second Edition' I like the book and it is very clear, but a lot to take in. It did cover lists, tuples, dictionaries and slicing early on like you do. I originally did try to use a 'list' with a 'for' loop but my list seemed to contain 8 different element when I printed it out ie. [0,1,0,0,0,1,1,0]. I also came into trouble when I tried to convert the binary to an integer instead of leaving it a string. I could not seem to get the 'list2', my dictionary, to except integers as the 'key'. O by the way, you are not teachign around Santa Barbara California are you?

    I should go back and re read the section on slices.

    Thanks again!

    -Lars
     

Share This Page