I need a very efficient way to iterate over a list and put its element as a dictionary keys and their count and last position as values in a list of size two.
For example, the list [1,1,1,2] must produce the dictionary {1:[3,2], 2:[1,3]}.
I expected this code to work:
myList = [1,1,1,2,2,2,3,4,5,5,6,7]
myDict = dict.fromkeys(myList, [0,0])
for i, e in enumerate(myList):
print(i, e)
myDict[e][0] = 1
myDict[e][1] = i
print(myDict)
But its output is
{1: [12, 11], 2: [12, 11], 3: [12, 11], 4: [12, 11], 5: [12, 11], 6: [12, 11], 7: [12, 11]}
instead of
{1: [3, 2], 2: [3, 5], 3: [1, 6], 4: [1, 7], 5: [2, 9], 6: [1, 10], 7: [1, 11]}
I did not expect this, because I considered iteration variables (i,e) as "usual" variables and therefore I expected a "copy" of them to be assigned, not a reference like it would happen in case of lists.
How to solve this problem?
CodePudding user response:
The issue comes from your dict.fromkeys(...)
call. It is assigning the same object [0,0]
to all keys, not a copy of this object.
The solution is to initialize your output dictionary as an empty dictionary. Then in your loop, first check if the key is already in the dictionary or not. If not then initialize the new key with [0,0]
, else perform the increment and index update as you already do in your code.
CodePudding user response:
I would assume this would be pretty fast - use a counter to get the number of occurrences and max/np.where to get the highest inedex.
import numpy as np
from collections import Counter
myList = [1,1,1,2,2,2,3,4,5,5,6,7]
a = np.array(myList)
{x[0]:[x[1],np.max(np.where(a==x[0]))] for x in Counter(a).most_common()}
Output
{1: [3, 2], 2: [3, 5], 5: [2, 9], 3: [1, 6], 4: [1, 7], 6: [1, 10], 7: [1, 11]}