Get value of dictionaries into separate lists - python

I am trying to get array by first key.
The names of the keys are always the same and the number of elements is the same.
[{'a': 1, 'b':41, 'c':324}, {'a': 1, 'b':12, 'c':65}, {'a': 2, 'b':36, 'c':12}]
expected output:
[{'b':41, 'c':324}, {'b':12, 'c':65}]
[{'b':36, 'c':12}]

Make a new dictionary that uses the values of the a keys as its keys.
newdict = {}
for d in data:
newdict.setdefault(d['a'], []).append({'b': d['b'], 'c': d['c']})
result = list(new_dict.values())

Related

Merge 2 dictionaries based on specific features

With 2 json file I am trying to merge certain features of one into the other. I converted the json into dictionaries I am trying to merge features from 1 dictionary into another. However I want specific features of one dictionary to merege with the other but not overwrite the initial values
Dictionary A: [{a:1,b:2,f:10},{a:2,b:4,f:10}]
Dictionary B: [{f:1,g:1,k:1},{f:2,g:2,k:1}]
Desired:
Dictionary C:[{a:1,b:2,f:10,g:1,k:1},{a:2,b:4,f:10,g:2,k:1}]
Loop through all dictionaries simultaneously
for x,y in zip(A,B):
x["g"]= y["g"]
x["k"]= y["k"]
You can iterate using zip then combine the dictionaries and filter out the keys that you don't want, you can use comprehension:
# Python 3.9+
>>> [y|x for x,y in zip(A, B)]
# output:
[{'f': 10, 'g': 1, 'k': 1, 'a': 1, 'b': 2},
{'f': 10, 'g': 2, 'k': 1, 'a': 2, 'b': 4}]
This will preserve the order and not overwrite any duplicate keys in A.
lst_a = [{'a':1,'b':2,'f':10},{'a':2,'b':4,'f':10}]
lst_b = [{'f':1,'g':1,'k':1},{'f':2,'g':2,'k':1}]
lst_c = []
for dict_a,dict_b in zip(lst_a,lst_b):
dict_b = {k:v for k,v in dict_b.items() if k not in dict_a}
lst_c.append(dict_a | dict_b)
print(lst_c)

Checking if value is present in the list of key-value pairs, if not present then add the new key-pair value from iterables (not overwriting same key)

If I used the not in it still appends the new key-pair value even if a specific value is already in the list.
dict1 = {'a': 0, 'a': 5, 'b': 1, 'c': 2}
list1 = [{'a': 0}] # This key-pair value is already in the list1 but
# still added from dict1.
new1 = []
new2 = []
for key, value in dict1.items():
if value not in list1:
new1.append(key)
new2.append(value)
new0 = {new1[i]: new2[i] for i in range(len(new1))}
list1.append(new0)
Desired output is:
list1 = [{'a': 0, 'a': 5, 'b': 1, 'c': 2}]
(As I dont want to overwrite the key/s)
As you do not provide example data, I have to make some guesses here. If I guessed incorrectly, please provide the required information.
You call .items on list1. A list does not have a items function. Instead, I suspect your list1 is actually a dictionary, which would like this for example:
list1 = {
"a":1,
"b":2,
"c":3
}
In your current loop, you check if the value is within list2. If list2 is actually a list, you're doing so correctly. However, based on your title I assume what you actually want to do is check if the key is in list2, and if not add the key:value to list2. You could not add a key:value pair to a list, so I assume that list2 shoudl also be a dictionary. You would be able to add them add as a tuple, but based on the title I assume that is not what you want.
If you actually want to add it as a key:value pair to a dictionary, you could do that as follows:
list2 = {}
for key, value in list1.items():
if key not in list2.keys(): # check if this key already exists
list2[key] = value # if not, add they key with the value
As list1 and list2 are not actually instances of list, but of dict I would recommend renaming your variables to avoid future confusion. Hope that helps!
EDIT after update in question
Your example data had a small mistake, as there were two a keys, meaning that the first {'a':0} would be overwritten within dict1 already.
dict1 = {'a': 0, 'b': 5, 'c': 1, 'd': 2}
list1 = [{'a': 0}]
As I understand it, you wish to check if the value is already containted within a list of dictionaries.
As such, we need to get all the values from these dictionaries.
As you do not want to overwrite any keys, it would need to be a list of dictionaries that each only have one key. As such, we can get each individual dictionary, get the keys. This returns an dict_keys object, which we can convert to a list. Since each dictionary within list1 always only has one key, we can just take the first from said lsit.
[list(x.values())[0] for x in list1]
Putting that within the loop we get
for key, value in dict1.items():
if not value in [list(x.values())[0] for x in list1]:
# If no dictionary exists within `list1` with this value
list1.append({key:value}) # then add it as a new dictionary
This would return
[{'a': 0}, {'b': 5}, {'c': 1}, {'d': 2}]
You could run this code again with a different dict1 and it would not overwrite keys within list1, for example with:
dict1 = {'a': 9}
the output would become
[{'a': 0}, {'b': 5}, {'c': 1}, {'d': 2}, {'a': 9}]

Over counting pairs in python loop

I have a list of dictionaries where each dict is of the form:
{'A': a,'B': b}
I want to iterate through the list and for every (a,b) pair, find the pair(s), (b,a), if it exists.
For example if for a given entry of the list A = 13 and B = 14, then the original pair would be (13,14). I would want to search the entire list of dicts to find the pair (14,13). If (14,13) occurred multiple times I would like to record that too.
I would like to count the number of times for all original (a,b) pairs in the list, when the complement (b,a) appears, and if so how many times. To do this I have two for loops and a counter when a complement pair is found.
pairs_found = 0
for i, val in enumerate( list_of_dicts ):
for j, vol in enumerate( list_of_dicts ):
if val['A'] == vol['B']:
if vol['A'] == val['B']:
pairs_found += 1
This generates a pairs_found greater than the length of list_of_dicts. I realize this is because the same pairs will be over-counted. I am not sure how I can overcome this degeneracy?
Edit for Clarity
list_of_dicts = []
list_of_dicts[0] = {'A': 14, 'B', 23}
list_of_dicts[1] = {'A': 235, 'B', 98}
list_of_dicts[2] = {'A': 686, 'B', 999}
list_of_dicts[3] = {'A': 128, 'B', 123}
....
Lets say that the list has around 100000 entries. Somewhere in that list, there will be one or more entries, of the form {'A' 23, 'B': 14}. If this is true then I would like a counter to increase its value by one. I would like to do this for every value in the list.
Here is what I suggest:
Use tuple to represent your pairs and use them as dict/set keys.
Build a set of unique inverted pairs you'll look for.
Use a dict to store the number of time a pair appears inverted
Then the code should look like this:
# Create a set of unique inverted pairs
inverted_pairs_set = {(d['B'],d['A']) for d in list_of_dicts}
# Create a counter for original pairs
pairs_counter_dict = {(ip[1],ip[0]):0 for ip in inverted_pairs_set]
# Create list of pairs
pairs_list = [(d['A'],d['B']) for d in list_of_dicts]
# Count for each inverted pairs, how many times
for p in pairs_list:
if p in inverted_pairs_set:
pairs_counter_dict[(p[1],p[0])] += 1
You can create a counter dictionary that contains the values of the 'A' and 'B' keys in all your dictionaries:
complements_cnt = {(dct['A'], dct['B']): 0 for dct in list_of_dicts}
Then all you need is to iterate over your dictionaries again and increment the value for the "complements":
for dct in list_of_dicts:
try:
complements_cnt[(dct['B'], dct['A'])] += 1
except KeyError: # in case there is no complement there is nothing to increase
pass
For example with such a list_of_dicts:
list_of_dicts = [{'A': 1, 'B': 2}, {'A': 2, 'B': 1}, {'A': 1, 'B': 2}]
This gives:
{(1, 2): 1, (2, 1): 2}
Which basically says that the {'A': 1, 'B': 2} has one complement (the second) and {'A': 2, 'B': 1} has two (the first and the last).
The solution is O(n) which should be quite fast even for 100000 dictionaries.
Note: This is quite similar to #debzsud answer. I haven't seen it before I posted the answer though. :(
I am still not 100% sure what it is you want to do but here is my guess:
pairs_found = 0
for i, dict1 in enumerate(list_of_dicts):
for j, dict2 in enumerate(list_of_dicts[i+1:]):
if dict1['A'] == dict2['B'] and dict1['B'] == dict2['A']:
pairs_found += 1
Note the slicing on the second for loop. This avoids checking pairs that have already been checked before (comparing D1 with D2 is enough; no need to compare D2 to D1)
This is better than O(n**2) but still there is probably room for improvement
You could first create a list with the values of each dictionary as tuples:
example_dict = [{"A": 1, "B": 2}, {"A": 4, "B": 3}, {"A": 5, "B": 1}, {"A": 2, "B": 1}]
dict_values = [tuple(x.values()) for x in example_dict]
Then create a second list with the number of occurrences of each element inverted:
occurrences = [dict_values.count(x[::-1]) for x in dict_values]
Finally, create a dict with dict_values as keys and occurrences as values:
dict(zip(dict_values, occurrences))
Output:
{(1, 2): 1, (2, 1): 1, (4, 3): 0, (5, 1): 0}
For each key, you have the number of inverted keys. You can also create the dictionary on the fly:
occurrences = {dict_values: dict_values.count(x[::-1]) for x in dict_values}

Python count multiple values in dictionary of list

I have been trying to count the values in a dictionary with respect to the key. However, I could not achieved desired result. I will demonstrate with more details below:
from collections import Counter
d = {'a': ['Adam','Adam','John'], 'b': ['John','John','Joel'], 'c': ['Adam','Adam','John}
# create a list of only the values you want to count,
# and pass to Counter()
c = Counter([values[1] for values in d.itervalues()])
print c
My output:
Counter({'Adam': 2, 'John': 1})
I want it to count everything in the list, not just first value of the list. Also, I want my result to be with respect to the key. I will show you my desired output below:
{'a': [{'Adam': 1, 'John': 2}, 'b':{'John': 2, 'Joel': 1}, 'c':{'Adam': 2, 'John': 1 }]}
Is it possible to get this desired output? Or anything close to it? I would like to welcome any suggestions or ideas that you have. Thank you.
Try this using dict comprehension
from collections import Counter
d = {'a': ['Adam','Adam','John'], 'b': ['John','John','Joel'], 'c': ['Adam','Adam','John'}
c = {i:Counter(j) for i,j in d.items()}
print c
You're picking only the first elements in the each list with values[1], instead, you want to iterate through each values using a for that follows the first:
>>> from collections import Counter
>>> d = {'a': ['Adam','Adam','John'], 'b': ['John','John','Joel'], 'c': ['Adam','Adam','John']}
>>> Counter([v for values in d.itervalues() for v in values]) # iterate through each value
Counter({'John': 4, 'Adam': 4, 'Joel': 1})

Removing dictionaries from a list on the basis of duplicate value of key

I am new to Python. Suppose i have the following list of dictionaries:
mydictList= [{'a':1,'b':2,'c':3},{'a':2,'b':2,'c':4},{'a':2,'b':3,'c':4}]
From the above list, i want to remove dictionaries with same value of key b. So the resultant list should be:
mydictList = [{'a':1,'b':2,'c':3},{'a':2,'b':3,'c':4}]
You can create a new dictionary based on the value of b, iterating the mydictList backwards (since you want to retain the first value of b), and get only the values in the dictionary, like this
>>> {item['b'] : item for item in reversed(mydictList)}.values()
[{'a': 1, 'c': 3, 'b': 2}, {'a': 2, 'c': 4, 'b': 3}]
If you are using Python 3.x, you might want to use list function over the dictionary values, like this
>>> list({item['b'] : item for item in reversed(mydictList)}.values())
Note: This solution may not maintain the order of the dictionaries.
First, sort the list by b-values (Python's sorting algorithm is stable, so dictionaries with identical b values will retain their relative order).
from operator import itemgetter
tmp1 = sorted(mydictList, key=itemgetter('b'))
Next, use itertools.groupby to create subiterators that iterate over dictionaries with the same b value.
import itertools
tmp2 = itertools.groupby(tmp1, key=itemgetter('b))
Finally, create a new list that contains only the first element of each subiterator:
# Each x is a tuple (some-b-value, iterator-over-dicts-with-b-equal-some-b-value)
newdictList = [ next(x[1]) for x in tmp2 ]
Putting it all together:
from itertools import groupby
from operator import itemgetter
by_b = itemgetter('b')
newdictList = [ next(x[1]) for x in groupby(sorted(mydictList, key=by_b), key=by_b) ]
A very straight forward approach can go something like this:
mydictList= [{'a':1,'b':2,'c':3},{'a':2,'b':2,'c':4},{'a':2,'b':3,'c':4}]
b_set = set()
new_list = []
for d in mydictList:
if d['b'] not in b_set:
new_list.append(d)
b_set.add(d['b'])
Result:
>>> new_list
[{'a': 1, 'c': 3, 'b': 2}, {'a': 2, 'c': 4, 'b': 3}]

Categories