4

I'm very new to Python and I need to create a function that divides by 2 the values in the lists inside the dictionary:

dic = {"A":[2,4,6,8], "B":[4,6,8,10]}

desired output:

dic2 = {"A":[1,2,3,4], "B":[2,3,4,5]}

I found this post

python: iterating through a dictionary with list values

which helped a little, but unfortunately is the "whatever" part of the example code that I can't figure out.

I tried this:

def divide(dic):
    dic2 = {}
    for i in range(len(dic)):
        for j in range(len(dic[i])):
            dic2[i][j] = dic[i][j]/2
    return dic2

I wrote different variations, but I keep getting a KeyError: 0 in the "for j..." line.

carlite71
  • 393
  • 1
  • 4
  • 16

7 Answers7

6

That's because dicts aren't like lists, they do not use indices, they use keys (like a label), and you can use dict.keys() to fetch a dict's keys.

Alternatively, just looping through a dict using for in loops through the keys:

dic = {"A": [2, 4, 6, 8], "B": [4, 6, 8, 10]}

for k in dic: # similar to `for key in dict.keys():`
    dic[k] = [x/2 for x in dic[k]]

print(dic)

Output:

{'A': [1.0, 2.0, 3.0, 4.0], 'B': [2.0, 3.0, 4.0, 5.0]}

If you don't want that decimal point, use // instead of /.

DjaouadNM
  • 22,013
  • 4
  • 33
  • 55
5

Behold, the power of comprehensions:

>>> dic = {"A":[2,4,6,8], "B":[4,6,8,10]}
>>> dic2 = {k:[v/2 for v in vs] for k,vs in dic.items()}
>>> dic2
{'A': [1, 2, 3, 4], 'B': [2, 3, 4, 5]}

There is a dict comprehension at the outer level, and an "inner" list comprehension used to divide the values in each list.

Graham
  • 7,431
  • 18
  • 59
  • 84
wim
  • 338,267
  • 99
  • 616
  • 750
3

You have to access elements of the dictionary using their key. In the example keys are 'A' and 'B'. You are trying to access the dictionary using an integer and that gives you the range error.

The following function works:

def divide_dic(dic):
    dic2 = {}

    # Iterate through the dictionary based on keys.
    for dic_iter in dic:

        # Create a copy of the dictionary list divided by 2.
        list_values = [ (x / 2) for x in  dic[dic_iter] ]

        # Add the dictionary entry to the new dictionary.
        dic2.update( {dic_iter : list_values} )

    return dic2
natersoz
  • 1,674
  • 2
  • 19
  • 29
  • This is inefficient because you perform dictionary lookups instead of iterating over key-value pairs; additionally, you create and destroy a temporary dict on each iteration. – Arya McCarthy May 25 '17 at 14:10
2

You can't necessarily numerically iterate over a dictionary—your range(len(dic)). (You shouldn't iterate over lists that way, either.) That's why dic[i] doesn't work—there's no dic[0]. Instead, iterate over its keys.

def divide(dic):
    dic2 = dic.copy()
    for key, value in dic:
        for i, _ in enumerate(value):  # Enumerate gives the index and value.
            dic2[key][i] = value[i]/2
    return dic2

Admittedly, comprehensions are a better way to go, but this preserves the form of what you did and illustrates where the problem was.

Arya McCarthy
  • 8,554
  • 4
  • 34
  • 56
2

To easily iterate over a dictionary, use for key in dictionary. Dividing the list by two is easily done with list comprehension

for k in dic1:
    dic1[k] = [x / 2 for x in dic1[k]]

in a function form

def divdict(d):
    for k in d:
        d[k] = [x/2 for x in d[k]]
1

You can try this with lambda:

the_funct = lambda x: x/2

dic = {"A":[2,4,6,8], "B":[4,6,8,10]}

new_dict = {a:map(the_funct, b) for a, b in dic.items()}
## for Python 3.5
new_dict = {a:[*map(the_funct, b)] for a, b in dic.items()}

The lambda function is coupled with map, which will iterate the function over every element in the values of the dictionary. By using dict comprehension, we can apply the lambda to every value.

InLaw
  • 2,537
  • 2
  • 21
  • 33
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
  • In Python 3, this gives `map` objects, not lists. This means it's only usable once. Prefer a list comprehension when it's not clear that you'll only iterate once through each list. – Arya McCarthy May 24 '17 at 03:49
1

I used a subtle variation of Wim's answer above (focus is on the comprehension using key):

dic = {"A":[2,4,6,8], "B":[4,6,8,10]}
dic2 = {k:[v/2 for v in dic[k]] for k in dic.keys()}

to get:

dic2
{'A': [1.0, 2.0, 3.0, 4.0], 'B': [2.0, 3.0, 4.0, 5.0]}
Grant Shannon
  • 4,709
  • 1
  • 46
  • 36