Search code examples
python-3.xdictionaryseq

creating a dictionary and assigning multiple values to each key using loops


I have the following dictionary, created with a set of keys, and I wish to add multiple values to each respective key using a loop (or any other method)

Note: *This is not a duplicate of a similar question, as I wish to do it without using default dictionary or set default

Code

def main():
    #Create an empty dictionary
    dict={}

    #create a sequence of keys (USING TUPLES) that would be used to store teacher's details
    seq=('name','salary','subject')

    #create a dictionary from the sequence above
    dict=dict.fromkeys(seq)
    print(str(dict))
    #........as of yet the dictionary does not have values

    #Add values to the dictionary
    dict=dict.fromkeys(seq,10)
    print("New Dictionary with values:",dict)
    #........this obviously doesn't make sense, as a teacher's name is unlikely to be all 10!!

    #Add multiple values to the the dictionary....
    teacher_detail_values=('Mr Moose','25k','Philosophy')
    for i in range(len(dict)):
        for j in range(len(teacher_detail_values)):
            dict=dict.fromkeys(seq,teacher_detail_values(j))
    print("Final New Dictionary with values:",dict)


main()

The code I am trying to work with in order to arrive at the most elegant solution is:

for i in range(len(dict)):
            for j in range(len(teacher_detail_values)):
                dict=dict.fromkeys(seq,teacher_detail_values(j))
        print("Final New Dictionary with values:",dict)

Any solutions with explanations appreciated. Please note that I do not wish to introduce any modules (so no default dict or set_default) as this is for beginner teaching/learning purposes

Expected output: Teaching/Learning aim: Using nested for loops

Final New Dictionary with values: {'name': Mr Moose, 'salary': 25K, 'subject': Philosophy}

Solution

  • dict.fromkeys does not add values to a dictionary.

    Instead, it is a class method for constructing dictionaries. This means that instead of assigning the dictionary constructed via fromkeys, you need to merge it into the existing dictionary. More in depth, fromkeys constructs a dictionary with multiple keys where each value is the same. This is not the best approach for what you are trying to achieve but I'll give code regardless.

    This confusion may have arrived out of the fact that you named your own dictionary dict, the name that the builtin class dict also has. You should probably give your variables more telling names, such as teacher.

    Also, you do not want to loop through each property and assign to it each value but instead you want to loop through all properties and assign a single value, the one paired to it.

    teacher = {}
    for i in range(len(seq)):
        prop_name = seq[i]
        prop_val  = teacher_detail_values[i]
        teacher.update(dict.fromkeys(prop_name, prop_val))
    

    There is a much more pythonic way even without introducing more modules

    teacher = dict(zip(seq, teacher_detail_values))
    

    I'll break down how it works:

    zip

    zip(seq1, seq2)
    

    This merges two sequences into a single sequence by pairing one element from the first one with one element from second one, until the shorter one is depleted. For example;

    zip((1, 2), (3, 4)) gives ((1, 3), (2, 4))
    zip((1, 2, 5), (3, 4)) gives ((1, 3), (2, 4)) since the second is only 2 elements long
    

    The constructor for dictionaries (dict denotes both the class name as well as working as a constructor for the class, this holds true (almost) all classes you will encounter in python) dict will behave in a special way when encountering a sequence of tuples with 2 elements, as the one produced by zip.

    It will examine each tuple in the sequence and map the first element of the tuple to the second element. So dict(zip((1, 2), (3, 4))) is the same as {1: 3, 2: 4}