Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reassign dictionary values

I have a dictionary like

{'A': 0, 'B': 1, 'C': 2, 'D': 3, etc}

How can I remove elements from this dictionary without creating gaps in values, in case the dictionary is not ordered?

An example:

I have a big matrix, where rows represent words, and columns represent documents where these words are encountered. I store the words and their corresponding indices as a dictionary. E.g. for this matrix

2 0 0
1 0 3
0 5 1
4 1 2

the dictionary would look like:

words = {'apple': 0, 'orange': 1, 'banana': 2, 'pear': 3}

If I remove the words 'apple' and 'banana', the matrix would contain only two rows. So the value of 'orange' in the dictionary should now equal 0 and not 1, and the value of 'pear' should be 1 instead of 3.

In Python 3.6+ dictionaries are ordered, so I can just write something like this to reassign the values:

i = 0
for k, v in words.items():
  v = i
  i += 1

or, alternatively

words = dict(zip(terms.keys(), range(0, matrix.shape[0])))

I think, this is far from being the most efficient way to change the values, and it wouldn't work with unordered dictionaries. How to do it efficiently? Is there any way to easily reassign the values in case the dictionary is not ordered?

like image 452
lawful_neutral Avatar asked Jun 03 '18 11:06

lawful_neutral


1 Answers

You could always keep an inverted dictionary that maps indices to words, and use that as a reference for keeping the order of the original dictionary. Then you could remove the words, and rebuild the dictionary again:

words = {'apple': 0, 'orange': 1, 'banana': 2, 'pear': 3}

# reverse dict for index -> word mappings
inverted = {i: word for word, i in words.items()}

remove = {'apple', 'banana'}

# sort/remove the words
new_words = [inverted[i] for i in range(len(inverted)) if inverted[i] not in remove]

# rebuild new dictionary
new_dict = {word: i for i, word in enumerate(new_words)}

print(new_dict)

Which Outputs:

{'orange': 0, 'pear': 1}

Note: Like the accepted answer, this is also O(n).

like image 90
RoadRunner Avatar answered Oct 11 '22 23:10

RoadRunner