How to manipulate the dictionary keys and values - python

I have a dictionary and I want to change the key of the dictionary into a unique value.
final_dict = {"name1":['raj','raj','raj'],"name2":['Rahul','Thor','max','Rahul'],"name3":['Jhon','Jhon'], "name4":['raj','raj'], "name5":['Rahul','Thor','max']}
First of all, I need unique values for each key like this
final_dict = {"name1":['raj'],"name2":['Thor','max','Rahul'],"name3":['Jhon'], "name4":['raj'], "name5":['Rahul','Thor','max']}
and then I need to convert the keys as values and vales as key
the final output I needed
output = {"raj":['name1','name4'], "('Thor','max','Rahul')":[name2,name5], "jhon":[name3]}
I tried this but I got only the unique values
mtype=[]
for key_name in final_dict:
a = set(final[key_name])
#print(tuple(a))
mtype.append(tuple(a))
print(mtype)
u = set(mtype)
print(u)

Here's a first shot at the problem. I'd carefully read through each line and make sure you understand what is going on. Feel free to ask follow ups in the comments!
from collections import defaultdict
input = { ... }
output = defaultdict(list)
for key, values in input.items():
unique_values = tuple(sorted(set(values)))
output[unique_values].append(key)
output = dict(output) # Transform defaultdict to a dict

Here is a straight forward way -
The set() takes care of the unique and the list comprehension below changes the dict items to item, key tuples.
dict.setdefault() allows appending each of the tuples into a blank list [] (key, value) pairs where the same key gets a list of values.
d = {}
l = [(i,k) for k,v in final_dict.items() for i in set(v)]
#print(l)
#[('raj', 'name1'), ('Thor', 'name2'), ('max', 'name2'), ('Rahul', 'name2'),
#('Jhon', 'name3'), ('raj', 'name4'), ('Thor', 'name5'), ('max', 'name5'),
#('Rahul', 'name5')]
for x, y in l:
d.setdefault(x, []).append(y)
print(d)
{'Jhon': ['name3'],
'Rahul': ['name2', 'name5'],
'Thor': ['name2', 'name5'],
'max': ['name2', 'name5'],
'raj': ['name1', 'name4']}

Related

Merge lists of dictionaries based on matching values in one key

I have a dictionary
dicte = [{'value':3, 'content':'some_string'}, {'value':4, 'content':'some_string1'}, {'value':4, 'content':'some_string2'}, {'value':4, 'content':'some_string3'}, {'value':4, 'content':'some_string4'}, {'value':5, 'content':'some_string5'}]
I want to be able to do an operation on that dictionary so that all the content that got the same values regarding the key "value" are regrouped and generate another dictionary based on that
The result here should be
new_dicte = [{'value':3, 'content':['some_string']}, {'value':4, 'content':['some_string1', 'some_string2', 'some_string3', 'some_string4']}, {'value':5, 'content':['some_string5']}]
What is the best pythonic way to do this ?
"Pythonic" is debatable, but you could build an intermediate dict to group by value:
grouped_by_value = {}
for item in dicte:
if item["value"] not in grouped_by_value:
grouped_by_value[item["value"]] = []
grouped_by_value[item["value"]].append(item["content"])
new_dicte = [{"value": key, "content": val} for key, val in grouped_by_value.items()]
The order of the elements in the new_dicte list will be the order that the values are encountered in the dicte list, assuming you are using a Python version where dicts are sorted by insertion order.
If you want to guarantee a specific ordering for new_dicte, you can sort the items of the grouped_by_value.items(), for example, by increasing "value" key.
Here's one way using dict.setdefault method to collect value-content pairs and unpacking later:
out = {}
for d in dicte:
out.setdefault(d['value'],[]).append(d['content'])
new_dicte = list(map(lambda x: dict(zip(('value','content'), x)), out.items()))
Here's another method that doesn't use an intermediate dictionary:
out = {}
for d in dicte:
if d['value'] not in out:
out[d['value']] = {'value':d['value'], 'content':[d['content']]}
else:
out[d['value']]['content'].append(d['content'])
new_dicte = list(out.values())
Output:
[{'value': 3, 'content': ['some_string']},
{'value': 4,
'content': ['some_string1', 'some_string2', 'some_string3', 'some_string4']},
{'value': 5, 'content': ['some_string5']}]
Best Pythonic is debatable but I would personally go with something like this,
import itertools
from collections import defaultdict
resp = defaultdict(list)
for key,group in itertools.groupby(d, key=lambda x: x["value"]):
for thing in group:
resp[key].append(thing.get("content"))
print(resp)
Output (can be adjusted to the way we want...)
{3: ['some_string'],
4: ['some_string1', 'some_string2', 'some_string3', 'some_string4'],
5: ['some_string5']}

Iterating over part of dictionary keys

I'm new to Python and I'm wondering how can I iterate over part of the keys in a list of dictionaries.
Suppose I have something like:
OrderedDict([('name', 'Anna'), ('AAA', '15'), ('BBB', '49'), ('CCC', '38')])
OrderedDict([('name', 'Bob'), ('AAA', '31'), ('BBB', '21'), ('CCC', '41')])
etc.
I need to retrieve and iterate over AAA, BBB, CCC (keys, not values), but:
only one time (not repeating for every dict in the list, but once, e.g. only for Anna)
skipping 'name', just those going after
in reality, I have many more of these keys (more than 10), so the question is how to iterate and not hard code it
I'd be very glad if you could help
Thanks a lot!
Just iterate over the first list, and check if it's name so you can skip it.
for key in list_of_dicts[0]:
if key != 'name':
print(key)
You can extract the keys from the first row by using:
keys = (key for key in list_of_dicts[0] if key != 'name')
Now you can iterate through the keys using something like:
for var in keys:
print(var)
I'm not sure if it's the best way, but I'd do it like this:
Dict = OrderedDict([('name', 'Anna'), ('AAA', '15'), ('BBB', '49'), ('CCC', '38')])
keys = [] # keys is an empty list
for i in Dict: # Iterate over all keys in the dictionary
if i != 'name': # Exclude 'name' from the list
keys.append(i) # Append each 'i' to the list
That will get you a list, keys, of each of the keys in Dict, excluding 'name'.
You can now iterate over the keys like this:
for i in keys:
print(i) # Do something with each key
And if you want to iterate over the values as well:
for i in keys:
print(Dict[i]) # Do something with each value
You would use a for loop. Here is an example (I called i since I do not know what you call the argument of that function):
i = [('name', 'Anna'), ('AAA', '15'), ('BBB', '49'), ('CCC', '38')]
for a in range(len(i)):
print(i[a][1])
The above gets the index of a, and inside the tuple (which has 2 elements so 0 or 1) gets the 2nd index.
NOTE:
You might want to make a nested for loop to get the ideals within the tuple.
Here is what you can do:
lst = [{...}, {...}, {...}, {...}, ...]
f = ['name']
for d in lst: # For every dict in the list
for k in d: # For every key in the dict
if k not in f: # If the key is not in the list f
# Do something
f.append(k) # Add that key to f so the program won't iterate through it again
UPDATE
(I just found out that every dict has the same keys, so there's no need to do all this checking):
lst = [{...}, {...}, {...}, {...}, ...]
for d in lst: # For every dict in the list
for k in d: # For every key in the dict
if k != 'name': # If the key is not 'name'
# Do something

List all keys in dictionaries which are inside a list. (Dictionary in a list)

Okay, not sure how to explain this problem but here goes.
This is my dictionary myDictionary = {'12/2019' : [{'1003' : 2}, {'1040' : 3}]}
I'm trying to list out the '1003', '1040'.
I've tried using this method:
for i in range(len(a['12/2019'])):
print(a['12/2019'][i].keys())
It kind of works however it returns me
dict_keys(['1003'])
dict_keys(['1040'])
Is there anyway I can just get 1030 and 1040 to be isolated from the ... dict_keys([''])?
You can iterate over the values of the dictionary, and if the value is a list, iterate over the dictionaries in the list, and append all the keys to the result
myDictionary = {'12/2019' : [{'1003' : 2}, {'1040' : 3}],
'11/2019': '1005', '10/2019': 1234,
'09/2019': [{'1006' : 2}, {'1042' : 3}],
'08/2019': (1,2)}
keys=[]
#Iterate over values
for value in myDictionary.values():
#If value is a list
if isinstance(value, list):
#Iterate over the list
for d in value:
#Add the keys to the result
keys.extend(list(d.keys()))
print(keys)
The output will be
['1003', '1040', '1006', '1042']
You can also do this via a list-comprehension, but it's not really readable, so I would avoid against it
[key for value in myDictionary.values() if isinstance(value, list) for d in value for key in d.keys()]
Iterate over the sub-dicts in the list, grabbing the keys:
for sub_dict in a['12/2019']:
for key, val in sub_dict.items():
print(key)
You can use a list-comprehension:
[k for v in myDictionary.values() for x in v for k in x]
In code:
myDictionary = {'12/2019' : [{'1003' : 2}, {'1040' : 3}]}
print([k for v in myDictionary.values() for x in v for k in x])
# ['1003', '1040']
You could do this by doing something like this
data = {'12/2019' : [{'1003' : 2}, {'1040' : 3}]}
# Data is a dictionary of where each value corresponding
# to the key is a list of dictionaries.
for k, v in data.items():
# v is a list of dictionaries
all_keys = []
for value in v:
all_keys.extend(list(value.keys()))
print (all_keys)
The result is ['1003', '1040']
This may be more than you need, but if the data you shared for the example is just a small subset of what you're really looking at, here's a recursive function that can go as deep as you want it to.
Since you seem to want to skip the keys in the outer most level, I put in a spot to allow you to skip over the keys at a given depth. You shouldn't set the level argument manually since the code will just update that for itself.
def list_keys(element, ignore_levels=[], level=1):
"""
Recursivly list keys found in an element.
element: item to inspect.
ignore_levels: list of numeric levels to ignore.
level: recursion depth level.
"""
keys = []
# add keys if we're not ignoring this level and set iterable to values
if isinstance(element, dict):
if level not in ignore_levels:
keys.extend(element.keys())
iterable = element.values()
# if we hve a list or tuple, we can iterate over it
elif isinstance(element, (list, tuple)):
iterable = element
# if we have a single value, it's not a key and there's nothing to iterate
else:
iterable = []
# Iterate over elements and append any keys found
for i in iterable:
subkeys = list_keys(i, ignore_levels, level + 1)
if subkeys:
keys.extend(subkeys)
return keys
d = {'12/2019': [{'1003': 2}, {'1040': 3}]}
print(list_keys(d, ignore_levels=[1]))
# ['1003', '1040']

combine common value based on some key in list of tuple

e.g
data = [ (item1, ('1-jan' ,45)) , (item2, ('21-jan',65)), (item1, ('21-jan',48))]
I like something like:
result = [ (item1, [('1-jan' ,45),('21-jan',48)]), (item2, [('21-jan',65)])]
to be precise I need final outcome
result = { item1: ('1-jan':45,'21-jan':48)), item2: ('21-jan':65)]
You can use dict.setdefault() to easily create groupings in a dictionary:
>>> data = [ ('item1', ('1-jan' ,45)) , ('item2', ('21-jan',65)), ('item1', ('21-jan',48))]
>>> result = {}
>>> for k, v in data:
result.setdefault(k, []).append(v)
>>> result
{'item2': [('21-jan', 65)], 'item1': [('1-jan', 45), ('21-jan', 48)]}
You can also use collections.defaultdict to achieve the same end.
If #Raymond's setdefault() doesn't work for you, try a defaultdict(list) object:
source
data = [ ("item1", ('1-jan' ,45)) , ("item2", ('21-jan',65)), ("item1", ('21-jan',48))]
from collections import defaultdict
out = defaultdict(list)
for key,value in data:
out[key].append(value)
print out
output
defaultdict(<type 'list'>, {'item2': [('21-jan', 65)], 'item1': [('1-jan', 45), ('21-jan', 48)]})
This is not as simple as iterating through each value and adding it to a dictionary. You must check to make sure that the key (item1, item2) are not in the dictionary first. If they are, you must append the value to the existing key.
Here you go:
data = [ ('item1', ('1-jan' ,45)) , ('item2', ('21-jan',65)), ('item1', ('21-jan',48))]
dataDict = {}
for i in range(len(data)):
if data[i][0] not in dataDict:
dataDict[data[i][0]] = data[i][1]
else:
dataDict[data[i][0]] += data[i][1]
As the above users have commented, you can use default dictionaries to make life more simple.

Extract different values from list of tuples

How to extract a list of different values from following list of tuples?
tuple = ((("test", 123), ("test", 465), ("test", 8910), ("test2", 123)))
I want to get a list like:
different_values = ("test", "test2")
Now I want to access all values by this "keys" and get them by a list:
test_values = (123, 456, 8910)
test2_values = (123)
How to do that?
I'd transform your data to a dictionary of lists:
d = {}
for k, v in tuples:
d.setdefault(k, []).append(v)
Now you can access the keys as d.keys(), and the list of values for each key k as d[k].
(Shortly, someone will step forward and claim a defaultdict would be better for this. Don't listen to them, it simply doesn't matter in this case.)

Categories

Resources