Search code examples
pythondictionarypython-3.6multiple-value

Return a multiple value dictionary within a function into a pretty format


So the first 2 steps I took to come to this point were as follows:

  1. I opened a textfile. The print-method provided me with this:

    ["string1","a","b","c"] 
    ["string2","d","e","f"]
    ["string3","g","h","i"] 
    ["string4","j","k","l"]
    
  2. I converted these lists into a dictionary. It looks like this now:

    dictionary = {"string1":["a","b","c"], "string2":["d","e","f"],
                  "string3":["g","h","i"], "string4":["j","k","l"]}  
    

My goal was to return this dictionary within a function, so that it looks like this when it's printed in a main function:

{
"string1":["a","b","c"],
"string2":["d","e","f"],
"string3":["g","h","i"],
"string4":["j","k","l"]}

I tried applying a newline before each key but it only prints this:

{"\nstring1":["a","b","c"], "\nstring2":["d","e","f"],"\nstring3":["g","h","i"], 
"\nstring4":["j","k","l"]}

This is my function (including the main function):

import csv

def read_dictionary():
    with open("text.tsv") as tsvfile:
        tsvreader = csv.reader(tsvfile, delimiter = "\t")
        d = {}
        for line in tsvreader:
            first_row = line[0:1] 
            rest_rows = line[1:]
            for strings in first_row: #converting lists into strings
                d["\n"+strings] = rest_rows
        return d

if __name__=="__main__":
   print(read_dictionary())

Solution

  • Dictionaries (like all built-in containers) are represented with their contents shown as representations, essentially using the repr() function on each. For strings, those are meant to be as helpful as possible in that they are shown as string literals that can simply be copied and pasted to recreate their value. That means they also show unprintable characters or characters with special meaning as escape sequences. Your newline characters are just such characters.

    In other words, you can't do what you want just by inserting \n characters in the string values.

    Instead, you need to do your own formatting if you really want to show your dictionary that way. Just print out the keys and values yourself:

    def represent_dict(d):
        print('{', end='')  # no newline
        first = True
        for key, value in d.items():
            # newline at the start, not end, with commas
            print('{}\n{!r}: {!r}'.format('' if first else ',', key, value), end='')
            first = False
        print('}')  # closing with a brace and a newline
    

    Remove the \n addition in your reading code; it can be simplified to just produce the dictionary directly with a dictionary comprehension:

    def read_dictionary():
        with open("text.tsv") as tsvfile:
            tsvreader = csv.reader(tsvfile, delimiter = "\t")
            return {row[0]: row[1:] for row in tsvreader}
    
    represent_dict(read_dictionary())
    

    You generally should keep presentation and data structure separate. Those newlines in the keys can easily cause issues elsewhere, and they are only there for the presentation output.

    Demo of the output:

    >>> dictionary = {"string1":["a","b","c"], "string2":["d","e","f"],
    ...               "string3":["g","h","i"], "string4":["j","k","l"]}
    >>> represent_dict(dictionary)
    {
    'string1': ['a', 'b', 'c'],
    'string2': ['d', 'e', 'f'],
    'string3': ['g', 'h', 'i'],
    'string4': ['j', 'k', 'l']}