Adding values to dictionary keys from a list of lists - python

I have the following list and dictionary:
list = [[1,2,2],[2,3,3],[3,4,4]
dict = {1:[], 2:[], 3:[]}
Let's say I wanted to append all values that proceed dict[keys] into their respective keys such that:
dict = {1:[2,2], 2:[3,3], 3:[4,4]}
I've attempted using multiple loops to accomplish this. However whenever I do that all values get searched and appended to each dict[key] simultaneously. Any help would be appreciated!

l = [[1,2,2],[2,3,3],[3,4,4]]
# last key wins
d = {sublist[0]:sublist[1:] for sublist in l}
print(d)
You construct the dictionary from your lists elements. Do not use list or dict as names, they shadow the built-ins.
sublist[0] is the first element, sublist[1:] are the rest of the elements of each item in l.
More about the syntax used here: PEP 274: Dict Comprehensions
Outputs:
{1: [2, 2], 2: [3, 3], 3: [4, 4]} # last key wins (no duplicates present)
If you need to merge as well, you can use:
# merging keys into values as list of sublists
l = [[2,2,2],[2,3,3],[3,4,4]]
d1 = {}
for sub in l:
# creates dict of { key: [ [int,...], [int,...] ], ... } for same keys
d1.setdefault(sub[0],[]).append(sub[1:])
or by flattening:
# merging keys into values as flattened list
d2 = {}
for sub in l:
# creates dict of { key: [ int,...,int,... ], ... } for same keys
d2.setdefault(sub[0],[]).extend(sub[1:])
Outputs:
{2: [[2, 2], [3, 3]], 3: [[4, 4]]} # merging keys into values as list of sublists
{2: [2, 2, 3, 3], 3: [4, 4]} # merging keys into values as flattened list
For merging I used dict.setdefault() you might want to take a peek at collections.defaultdict() which I get assured is better suited.

Related

Converting a list of "pairs" into a dictionary of dictionaries?

This question was previously asked here with an egregious typo: Counting "unique pairs" of numbers into a python dictionary?
This is an algorithmic problem, and I don't know of the most efficient solution. My idea would be to somehow cache values in a list and enumerate pairs...but that would be so slow. I'm guessing there's something useful from itertools.
Let's say I have a list of integers whereby are never repeats:
list1 = [2, 3]
In this case, there is a unique pair 2-3 and 3-2, so the dictionary should be:
{2:{3: 1}, 3:{2: 1}}
That is, there is 1 pair of 2-3 and 1 pair of 3-2.
For larger lists, the pairing is the same, e.g.
list2 = [2, 3, 4]
has the dicitonary
{2:{3:1, 4:1}, 3:{2:1, 4:1}, 4:{3:1, 2:1}}
(1) Once the size of the lists become far larger, how would one algorithmically find the "unique pairs" in this format using python data structures?
(2) I mentioned that the lists cannot have repeat integers, e.g.
[2, 2, 3]
is impossible, as there are two 2s.
However, one may have a list of lists:
list3 = [[2, 3], [2, 3, 4]]
whereby the dictionary must be
{2:{3:2, 4:1}, 3:{2:2, 4:1}, 4:{2:1, 3:1}}
as there are two pairs of 2-3 and 3-2. How would one "update" the dictionary given multiple lists within a list?
EDIT: My ultimate use case is, I want to iterate through hundreds of lists of integers, and create a single dictionary with the "counts" of pairs. Does this make sense? There might be another data structure which is more useful.
For the nested list example, you can do the following, making use of itertools.permutations and dict.setdefault:
from itertools import permutations
list3 = [[2, 3], [2, 3, 4]]
d = {}
for l in list3:
for a, b in permutations(l, 2):
d[a][b] = d.setdefault(a, {}).setdefault(b, 0) + 1
# {2: {3: 2, 4: 1}, 3: {2: 2, 4: 1}, 4: {2: 1, 3: 1}}
For flat lists l, use only the inner loop and omit the outer one
For this example I'll just use a list with straight numbers and no nested list:
values = [3, 2, 4]
result = dict.from_keys(values)
for key, value in result.items():
value = {}
for num in values:
if num != key:
value[num] = 1
This creates a dict with each number as a key. Now in each key, make the value a nested dict who's contents are num: 1 for each number in the original values list if it isn't the name of the key that we're in
use defaultdict with permutations
from collections import defaultdict
from itertools import permutations
d = defaultdict(dict)
for i in [x for x in permutations([4,2,3])]:
d[i[0]] = {k: 1 for k in i[1:]}
output is
In [22]: d
Out[22]: defaultdict(dict, {2: {3: 1, 4: 1}, 4: {2: 1, 3: 1}, 3: {2: 1, 4: 1}})
for inherit list of lists https://stackoverflow.com/a/52206554/8060120

Get dictionary mapping values to reference ID

I have a list of numpy arrays like the following:
list_list = [np.array([53, 5, 2, 5, 5, 2, 1, 5, 9]), np.array([6, 4, 1,2, 53, 23, 1, 4])]
and a list of IDs for each array above:
ID = [6, 2]
How can I get a dictionary that for each unique value in list_list, I get a list of the IDs which contain it?
For example, for this very simple example, I want something like:
{53: [6, 2], 5: [6], 2: [6, 2], 1: [6, 2], etc}
My actual list_list is over 1000 lists long, with each numpy array containing around 10 million value, so efficiency in the solution is key.
I know that dict(zip(ID, list_list)) will give me a dictionary corresponding an ID with all of its values, but it won't give me a value corresponding to IDs, which is what I want.
Thanks!
The best way to approach a problem like this is to break it into smaller steps. Describe these in a combination of English and pseudo-python as seems appropriate. You seem to have the right idea to get started with zip(ID, list_list). This creates the association between the two lists as we discussed in the comments.
So what next? Well, we want to build a dictionary with the values in list_list as keys. To do so, we need to iterate over the list returned by zip():
for id, list in zip(ID, list_list):
pass
And then we need to iterate over the elements of list to determine the keys of the dictionary:
for id, list in zip(ID, list_list):
for x in list:
pass
Now we need an empty dictionary to add things to:
d = {}
for id, list in zip(ID, list_list):
for x in list:
pass
Next, we need to get a list for the dictionary if it exists. If it doesn't exist, we can use an empty list instead. Then append the id to the list and put it into the dictionary:
d = {}
for id, list in zip(ID, list_list):
for x in list:
l = d.get(x, [])
l.append(id)
d[x] = l
Notice how I describe in words what to do at each step and then translate it into Python. Breaking a problem into small steps like this is a key part of developing your skills as a programmer.
We iterate the Zip(ID,list_list) and to get only the unique elements in the lis by creating a set of it.
Then we will iterate through this set and if that element is not allready present in the dictionary we add it to the dictionary if it's already present we append the id.
import numpy as np
list_list = [np.array([53, 5, 2, 5, 5, 2, 1, 5, 9]), np.array([6, 4, 1,2, 53, 23, 1, 4])]
ID = [6, 2]
dic={}
for id,lis in zip(ID,list_list):
lis=set(lis)
for ele in lis:
if ele not in dic:
dic[ele]=[id]
else:
dic[ele].append(id)
print(dic)
{1: [6, 2], 2: [6, 2], 5: [6], 9: [6], 53: [6, 2], 4: [2], 6: [2], 23: [2]}

how to get all the values in a dictionary with the same key? [duplicate]

I want to add multiple values to a specific key in a python dictionary. How can I do that?
a = {}
a["abc"] = 1
a["abc"] = 2
This will replace the value of a["abc"] from 1 to 2.
What I want instead is for a["abc"] to have multiple values (both 1 and 2).
Make the value a list, e.g.
a["abc"] = [1, 2, "bob"]
UPDATE:
There are a couple of ways to add values to key, and to create a list if one isn't already there. I'll show one such method in little steps.
key = "somekey"
a.setdefault(key, [])
a[key].append(1)
Results:
>>> a
{'somekey': [1]}
Next, try:
key = "somekey"
a.setdefault(key, [])
a[key].append(2)
Results:
>>> a
{'somekey': [1, 2]}
The magic of setdefault is that it initializes the value for that key if that key is not defined. Now, noting that setdefault returns the value, you can combine these into a single line:
a.setdefault("somekey", []).append("bob")
Results:
>>> a
{'somekey': [1, 2, 'bob']}
You should look at the dict methods, in particular the get() method, and do some experiments to get comfortable with this.
How about
a["abc"] = [1, 2]
This will result in:
>>> a
{'abc': [1, 2]}
Is that what you were looking for?
Append list elements
If the dict values need to be extended by another list, extend() method of lists may be useful.
a = {}
a.setdefault('abc', []).append(1) # {'abc': [1]}
a.setdefault('abc', []).extend([2, 3]) # a is now {'abc': [1, 2, 3]}
This can be especially useful in a loop where values need to be appended or extended depending on datatype.
a = {}
some_key = 'abc'
for v in [1, 2, 3, [2, 4]]:
if isinstance(v, list):
a.setdefault(some_key, []).extend(v)
else:
a.setdefault(some_key, []).append(v)
a
# {'abc': [1, 2, 3, 2, 4]}
Append list elements without duplicates
If there's a dictionary such as a = {'abc': [1, 2, 3]} and it needs to be extended by [2, 4] without duplicates, checking for duplicates (via in operator) should do the trick. The magic of get() method is that a default value can be set (in this case empty set ([])) in case a key doesn't exist in a, so that the membership test doesn't error out.
a = {some_key: [1, 2, 3]}
for v in [2, 4]:
if v not in a.get(some_key, []):
a.setdefault(some_key, []).append(v)
a
# {'abc': [1, 2, 3, 4]}

Sum values in a dict of lists

If I have a dictionary such as:
my_dict = {"A": [1, 2, 3], "B": [9, -4, 2], "C": [3, 99, 1]}
How do I create a new dictionary with sums of the values for each key?
result = {"A": 6, "B": 7, "C": 103}
Use sum() function:
my_dict = {"A": [1, 2, 3], "B": [9, -4, 2], "C": [3, 99, 1]}
result = {}
for k, v in my_dict.items():
result[k] = sum(v)
print(result)
Or just create a dict with a dictionary comprehension:
result = {k: sum(v) for k, v in my_dict.items()}
Output:
{'A': 6, 'B': 7, 'C': 103}
Try This:
def sumDictionaryValues(d):
new_d = {}
for i in d:
new_d[i]= sum(d[i])
return new_d
Just a for loop:
new = {}
for key in dict:
new_d[key]= sum(d[key])
new the dictionary having all the summed values
One liners- for the same, just demonstrating some ways to get the expected result,in python3
my_dict = {"A": [1, 2, 3], "B": [9, -4, 2], "C": [3, 99, 1]}
Using my_dict.keys():- That returns a list containing the my_dict's keys, with dictionary comprehension.
res_dict = {key : sum(my_dict[key]) for key in my_dict.keys()}
Note that my_dict.keys() produce a list of keys in the dictionary,
But python dictionary data structure also got an iterator implementation to loop
through keys, (which is faster, but not recommended always) so, this
will also give same result,
res_dict = {key : sum(my_dict[key]) for key in my_dict}
Using my_dict.items():- That returns a list containing a tuple for each key
value pair of dictionary, by unpacking them gives a best single line solution for this,
res_dict = {key : sum(val) for key, val in my_dict.items()}
Using my_dict.values():- That returns a list of all the values in the
dictionary(here the list of each lists),
note:- This one is not intended as a direct solution, just for demonstrating the three python methods used to traverse through a dictionary
res_dict = dict(zip(my_dict.keys(), [sum(val) for val in my_dict.values()]))
The zip function accepts iterators(lists, tuples, strings..), and pairs similar indexed items together and returns a zip object, by using dict it is converted back to a dictionary.

How to find 2 items in a list that are the same in Python

I have a list populated with ~100 names. The names in this list either occur once or twice and I would like to go through the list to find names that occur twice and names that only occur once. I will also need the position of the reoccurring names in the list and the positions of the names that only appear once.
I'm not sure how I would go about doing this because all the methods I can think of are inefficient as they would go through the whole list even if they have already found a match. Other methods that I can think of would return two duplicate positions. The names that occur twice will not necessarily be adjacent to each other.
For example, if this was the list:
mylist = [ 1, 2, 3, 1, 4, 4, 5, 6]
I would need something that outputs (something like):
[[0,3],[1],[2],[4,5],[6],[7]]
With those numbers being the positions of the duplicate names and the position of the names that occur once.
I am by no means an expert so any help would be appreciated.
You can use enumerate to get the pairs contain index of each element and the element itself then loop over it and store the items as key and indices as values using a collections.OrderedDict (to preserve the order) and dict.setdefault method:
>>> from collections import OrderedDict
>>> d=OrderedDict()
>>> for i,j in enumerate(mylist):
... d.setdefault(j,[]).append(i)
...
>>> d.values()
[[0, 3], [1], [2], [4, 5], [6], [7]]
I would use a dictionary:
mylist = [1,2,3,1,4,4,5,6]
dic = {}
for i in range(0,len(mylist)):
if mylist[i] in dic:
dic[mylist[i]].append(i)
else:
dic[mylist[i]] = [i]
print dic.values()
# prints [[0, 3], [1], [2], [4, 5], [6], [7]]

Categories