zelenov aleksey
zelenov aleksey

Reputation: 398

how to update values in dictionary of lists

I'm trying to update values in dictionary of lists EX: I have a dictionary input:

d={0: [0,1], 1:[1],2:[2],3:[3]}

and pair [0,2] and I want to replace every 0 in dict with 0,2 and increase each value >2 by 1, so here the expected output:

{0: [0,2,1], 1:[1],2:[2],3:[4]}

I tried to iterate over all values, but it didn't make the trick properly

def update_dict(_dict,_pair):
    for i in range(len(_dict.keys())):
        for j in range(len(_dict.values()[i])):
            if dict[i][j]==_pair[0]:
                dict[i][j].remove(_pair[0])
                dict[i].append(_pair)
    return _dict

How do I achieve that? Thanks in advance for any help

Upvotes: 0

Views: 454

Answers (5)

Victoria Stuart
Victoria Stuart

Reputation: 5072

"How to update values within lists within a dictionary?" is a good question. Suppose I have a dictionary of lists and I want to change a value within one of those lists.

import copy
i = 1
input_sentence_dict = {i: []}
input_sentence_dict[1] = "['I', 'have', 'a', 'gift', 'for', 'Carmine', '.']"
input_sentence_dict[2] = "['I', 'gave', 'it', 'to', 'her', '.']"
import pprint
pp = pprint.PrettyPrinter(indent=4)
print('input_sentence_dict:')
pp.pprint(input_sentence_dict)
'''
input_sentence_dict:
{   1: ['I', 'have', 'a', 'gift', 'for', 'Carmine', '.'],
    2: ['I', 'gave', 'it', 'to', 'her', '.']}
'''

output_sentence_dict = copy.deepcopy(input_sentence_dict)
print('output_sentence_dict:')
pp.pprint(output_sentence_dict)
'''
output_sentence_dict:
{   1: ['I', 'have', 'a', 'gift', 'for', 'Carmine', '.'],
    2: ['I', 'gave', 'it', 'to', 'her', '.']}
'''

# example of indexing:
print(output_sentence_dict[2][1:3])
# ['gave', 'it']

Through indexing, you can easily change a value within one of those lists. For example:

output_sentence_dict[2][2] = 'a book'
pp.pprint(output_sentence_dict) 
'''
{   1: ['I', 'have', 'a', 'gift', 'for', 'Carmine', '.'],
    2: ['I', 'gave', 'a book', 'to', 'her', '.']}
'''

Note. If you simply copy a dictionary (e.g. dict2 = dict1), edits to one affects the other. You need to "deepcopy" the source dictionary to ensure that you work on a truly different object, leaving the source object unperturbed.

import copy
dict2 = copy.deepcopy(dict1)

You may then edit dict2, leaving dict1 unaltered.

This is well-described in this StackOverflow thread: How to copy a dictionary and only edit the copy

Working with "shallow copies," e.g.

dict2 = dict1
# or
dict2 = dict(dict1)

will result in silent errors. In the example above, if you do not use copy.deepcopy(dict), changes made to output_sentence_dict will also silently propagate to input_sentence_dict.

Upvotes: 1

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

Another alternative solution:

d={0: [0,1], 1:[1],2:[2],3:[3]}

for k,a in d.items():
    for key, digit in enumerate(a):
        if digit == 0: a[key:key+1] = [0,2]
        if digit > 2: a[key] += 1

print(d)

The output:

{0: [0, 2, 1], 1: [1], 2: [2], 3: [4]}

Upvotes: 1

Dmitry
Dmitry

Reputation: 2096

There is a large number of solutions. For example:

d = {0: [0,1], 1:[1],2:[2],3:[3]}
new_d = dict()
for k in d:
    new_d[k] = sum([i == 0 and [0, 2] or i > 2 and \
                    [i + 1] or [i] for i in d[k]], [])

or

d = {0: [0,1], 1:[1],2:[2],3:[3]}
new_d = dict([(k, sum([i == 0 and [0, 2] or i > 2 \ 
               and [i + 1] or [i] for i in v], [])) for k, v in d.items()])

Upvotes: 1

DeepSpace
DeepSpace

Reputation: 81594

And if you still want to use a dictionary, this will do:

d = {0: [0,1], 1:[1],2:[2],3:[3]}

for k, li in d.items():
    for i, v in enumerate(li[:]):
        if v == 0:
            li.insert(i + 1, 2)
        elif v > 2:
            d[k][i] += 1

print(d)
# {0: [0, 2, 1], 1: [1], 2: [2], 3: [4]}

Just keep in mind that the keys order is not guaranteed.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1121476

You don't need a dictionary here, you want a list; you have an ordered series of keys starting at 0, indices of a list would more efficiently serve that need:

l = [[0,1], [1], [2], [3]]

You can produce the desired output:

for i, nested in enumerate(l):
    # replace all 0 values with 1, 2
    while 0 in nested:
        zero_index = nested.index(0)
        nested[zero_index:zero_index + 1] = [1, 2]
    # increment values in the nested list if the index is over 2:
    if i > 2:
        nested[:] = [v + 1 for v in nested]

This alters the original nested lists in-place.

Upvotes: 3

Related Questions