Related
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?
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.
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]}
I, have a dictionary say {0:[1,2,3],1[1,2,3],2:[1,2,3],3:[1,2,4],4:[1,2,4],5:[1,2,4]}. there are some duplicate values but the keys are different. when i append a value to list corresponding to key 0 python also adds the value to other duplicates what i don't need.
my code :-
for k, v in f.items():
if k == 0:
v.append(1)
result:-
{0:[1,2,3,1],1[1,2,3,1],2:[1,2,3,1],3:[1,2,4],4:[1,2,4],5:[1,2,4]}
what i want is :-
{0:[1,2,3,1],1[1,2,3],2:[1,2,3],3:[1,2,4],4:[1,2,4],5:[1,2,4]}
I guess your dictionary is faulty. It should be like this:
f={0:[1,2,3],1:[1,2,3],2:[1,2,3],3:[1,2,4],4:[1,2,4],5:[1,2,4]}
for k,v in f.items():
if k==0:
v.append(1)
print(f)
Output: {0: [1, 2, 3, 1], 1: [1, 2, 3], 2: [1, 2, 3], 3: [1, 2, 4], 4: [1, 2, 4], 5: [1, 2, 4]}
Isn't it what you want?
I have created a dict with key and empty values. i am trying to update the values based on the condition whether the key is divisible by any other number. i am able to get the output based on the code
adict = {}
for i in range (1,7):
adict[i] = []
for j in range (1,i+1):
if(i%j==0):
print ((j),end='')
i got the following output :11213124151236
i am looking for the desired output that updates the value for the dict : {1:[1],2:[1,2],3:[1,3],4:[1,2,4],5:[1,5],6:[1,2,3,6]}
Have a look at the code below,
adict = {}
for i in range (1,7):
adict[i] = []
for j in range (1,i+1):
if(i%j == 0):
adict[i].append(j)
print(adict)
Output:
{1: [1], 2: [1, 2], 3: [1, 3], 4: [1, 2, 4], 5: [1, 5], 6: [1, 2, 3, 6]}
Is there a possibility to create a dict from two lists with same key occurring multiple times without iterating over the whole dataset?
Minimal example:
keys = [1, 2, 3, 2, 3, 4, 5, 1]
values = [1, 2, 3, 4, 5, 6, 7, 8]
# hoped for result:
dictionary = dict(???)
dictionary = {1 : [1,8], 2:[2,4], 3:[3,5], 4:[6], 5:[7]}
When using zip the key-value-pair is inserted overwriting the old one:
dictionary = dict(zip(keys,values))
dictionary = {1: 8, 2: 4, 3: 5, 4: 6, 5: 7}
I would be happy with a Multidict as well.
This is one approach that doesn't require 2 for loops
h = defaultdict(list)
for k, v in zip(keys, values):
h[k].append(v)
print(h)
# defaultdict(<class 'list'>, {1: [1, 8], 2: [2, 4], 3: [3, 5], 4: [6], 5: [7]})
print(dict(h))
# {1: [1, 8], 2: [2, 4], 3: [3, 5], 4: [6], 5: [7]}
This is the only one-liner I could do.
dictionary = {k: [values[i] for i in [j for j, x in enumerate(keys) if x == k]] for k in set(keys)}
It is far from readable. Remember that clear code is always better than pseudo-clever code ;)
Here is an example that I think is easy to follow logically. Unfortunately it does not use zip like you would prefer, nor does it avoid iterating, because a task like this has to involve iterating In some form.
# Your data
keys = [1, 2, 3, 2, 3, 4, 5, 1]
values = [1, 2, 3, 4, 5, 6, 7, 8]
# Make result dict
result = {}
for x in range(1, max(keys)+1):
result[x] = []
# Populate result dict
for index, num in enumerate(keys):
result[num].append(values[index])
# Print result
print(result)
If you know the range of values in the keys array, you could make this faster by providing the results dictionary as a literal with integer keys and empty list values.
I have a list. Let's say [3,4,2,3,4,2,1,4,5].
I need to create a dictionary from the indexes of the elements.
Here in this case, I need to create a dict as follows:
{
'3':[0,3],
'4':[1,4,7],
'2':[2,5],
'1':[6],
'5':[8]
}
where the element values are the indexes of the keys in list provided.
I've tried. But was able to change the values as integers only. But unable to make them as list.
Is there any way to do this with just 1 for loop?
The code I've tried:
d=dict()
ll=[1,2,1,2,1,2,3,4,5,5,4,2,4,6,5,6,78,3,2,4,5,7,8,9,4,4,2,2,34,5,6,3]
for i,j in enumerate(ll):
d[j].append(i)
print(d)
You can use collections.defaultdict with enumerate for an O(n) solution:
from collections import defaultdict
d = defaultdict(list)
A = [3,4,2,3,4,2,1,4,5]
for idx, val in enumerate(A):
d[val].append(idx)
print(d)
defaultdict(list, {1: [6], 2: [2, 5], 3: [0, 3], 4: [1, 4, 7], 5: [8]})
This will work, the key thing you're looking for is the enumerate() function:
list_to_convert = [3,4,2,3,4,2,1,4,5]
out_dict = {}
for idx, val in enumerate(list_to_convert):
if val in out_dict:
out_dict[val].append(idx)
else:
out_dict[val] = [idx,]
print (out_dict)
Gives:
{3: [0, 3], 4: [1, 4, 7], 2: [2, 5], 1: [6], 5: [8]}
mylist = [3, 4, 2, 3, 4, 2, 1, 4, 5]
d = {}
for index, item in enumerate(mylist):
d.setdefault(item, []).append(index)
results in
{3: [0, 3], 4: [1, 4, 7], 2: [2, 5], 1: [6], 5: [8]}
Why? Well, we iterate over the list, and for each item, we first make sure that there is a list in the dictionary mapped to by this item. Then we append the respective index to that list. What results is a dictionary which maps each seen item to a list of indexes it was found at.
The solution is similar to jpp's solution, except of the part with .setdefault(), which creates an empty list in every loop run, while the defaultdict approach only creates new lists if needed.
Another approach could be a dict subclass which implements __missing__. This is called whenever a key isn't present.
class ListDict(dict):
def __missing__(self, key):
l = []
self[key] = l
return l
and then just do d[item].append(index). Now, whenever a key is not found, __missing__() is called which "fixes" the problem. See also How can I call __missing__ from dict for this.
You can use a set:
d = [3,4,2,3,4,2,1,4,5]
new_d = {i:[c for c, a in enumerate(d) if i == a] for i in set(d)}
Output:
{1: [6], 2: [2, 5], 3: [0, 3], 4: [1, 4, 7], 5: [8]}