I just want to know a easy way to extract all data with same key "Cat" from the dictionary into another array.
From the below dictionary..
All data with key "Cat: Book" should be in a separate array and key "Cat: pen" in another.
This dictionary is dynamic and more different "Cat" values can come in.
category= [{'Cat':'Book','Item':'LongBook','Qty':'25'},
{'Cat':'Book','Item':'Diary','Qty':'20'},
{'Cat':'Pen','Item':'BallPoint','Qty':'30'}]
It is quite difficult to understand what do you really need. Anyway try to take a look at the following code that uses defaultdict:
category= [{'Cat':'Book','Item':'LongBook','Qty':'25'},
{'Cat':'Book','Item':'Diary','Qty':'20'},
{'Cat':'Pen','Item':'BallPoint','Qty':'30'}]
from collections import defaultdict
output = defaultdict(list)
for row in category:
output['Cat' + ':' + row['Cat']].append(row)
print output.values()
>>>[[{'Item': 'BallPoint', 'Qty': '30', 'Cat': 'Pen'}], [{'Item': 'LongBook', 'Qty': '25', 'Cat': 'Book'}, {'Item': 'Diary', 'Qty': '20', 'Cat': 'Book'}]]
Or better use groupby:
category= [{'Cat':'Book','Item':'LongBook','Qty':'25'},
{'Cat':'Book','Item':'Diary','Qty':'20'},
{'Cat':'Pen','Item':'BallPoint','Qty':'30'}]
from itertools import groupby
for key, vals in groupby(category, lambda x: x['Cat']):
print key, list(vals)
>>>Book [{'Item': 'LongBook', 'Qty': '25', 'Cat': 'Book'}, {'Item': 'Diary', 'Qty': '20', 'Cat': 'Book'}]
>>>Pen [{'Item': 'BallPoint', 'Qty': '30', 'Cat': 'Pen'}]
Related
I am using for loop in python and every loop creates a dictionary. I have the below set of dictionaries created.
{'name': 'xxxx'}
{'name': 'yyyy','age':'28'}
{'name': 'zzzz','age':'27','sex':'F'}
My requirement is to compare all the dictionaries created and find out the missing key values and add the key to missing dictionaries and order every dictionary based on key. Below is the expected output
Expected output:
{'age':'','name': 'xxxx','sex':''}
{'age':'28','name': 'yyyy','sex':''}
{'age':'27','name': 'zzzz','sex':'F'}
How to achieve this in python.
If you want to modify the dicts in-place, dict.setdefault would be easy enough.
my_dicts = [
{'name': 'xxxx'},
{'name': 'yyyy','age':'28'},
{'name': 'zzzz','age':'27','sex':'F'},
]
desired_keys = ['name', 'age', 'sex']
for d in my_dicts:
for key in desired_keys:
d.setdefault(key, "")
print(my_dicts)
prints out
[
{'name': 'xxxx', 'age': '', 'sex': ''},
{'name': 'yyyy', 'age': '28', 'sex': ''},
{'name': 'zzzz', 'age': '27', 'sex': 'F'},
]
If you don't want to hard-code the desired_keys list, you can make it a set and gather it from the dicts before the loop above.
desired_keys = set()
for d in my_dicts:
desired_keys.update(set(d)) # update with keys from `d`
Another option, if you want new dicts instead of modifying them in place, is
desired_keys = ... # whichever method you like
empty_dict = dict.fromkeys(desired_keys, "")
new_dicts = [{**empty_dict, **d} for d in my_dicts]
EDIT based on comments:
This doesn't remove keys that are not there in desired keys.
This will leave only the desired keys:
desired_keys = ... # Must be a set
for d in my_dicts:
for key in desired_keys:
d.setdefault(key, "")
for key in set(d) - desired_keys:
d.pop(key)
However, at that point it might be easier to just create new dicts:
new_dicts = [
{key: d.get(value, "") for key in desired_keys}
for d in my_dicts
]
data = [{'name': 'xxxx'},
{'name': 'yyyy','age':'28'},
{'name': 'zzzz','age':'27','sex':'F'}]
First get the maximum, to get all the keys.
Then use dict.get to get default value as empty string for each of the keys, and sort the dictionary on key, you can combine List-comprehension and dict-comprehension:
allKD = max(data, key=len)
[dict(sorted({k:d.get(k, '') for k in allKD}.items(), key=lambda x:x[0])) for d in data]
OUTPUT:
[{'age': '', 'name': 'xxxx', 'sex': ''},
{'age': '28', 'name': 'yyyy', 'sex': ''},
{'age': '27', 'name': 'zzzz', 'sex': 'F'}]
One approach:
from operator import or_
from functools import reduce
lst = [{'name': 'xxxx'},
{'name': 'yyyy', 'age': '28'},
{'name': 'zzzz', 'age': '27', 'sex': 'F'}]
# find all the keys
keys = reduce(or_, map(dict.keys, lst))
# update each dictionary with the complement of the keys
for d in lst:
d.update(dict.fromkeys(keys - d.keys(), ""))
print(lst)
Output
[{'name': 'xxxx', 'age': '', 'sex': ''}, {'name': 'yyyy', 'age': '28', 'sex': ''}, {'name': 'zzzz', 'age': '27', 'sex': 'F'}]
I'm writing a function that returns two values which will form the key-value pair of a dictionary. This function will be used to create a dictionary with dictionary comprehension. However, using dictionary comprehension the pair of values need to be provided in the format 'key: value'. To accomplish this, I have to call the function twice. Once for the key, and once for the value. For example,
sample_list = [['John', '24', 'M', 'English'],
['Jeanne', '21', 'F', 'French'],
['Yuhanna', '22', 'M', 'Arabic']]
def key_value_creator(sample_list):
key = sample_list[0]
value = {'age': sample_list[1],
'gender': sample_list[2],
'lang': sample_list[3]}
return key, value
dictionary = {key_value_creator(item)[0]: \
key_value_creator(item)[1] for item in sample_list}
As you can see, the function is called twice to generate values that can be generated in one run. Is there a way to return the values in a format that can be usable by the comprehension? If that is possible, the function need only be called once, as such:
dictionary = {key_value_creator(item) for item in sample_list}
As far as I have seen, other ways of returning multiple values is to return them in the form of a dictionary or list,
return {'key': key, 'value': value}
return [key, value]
but either way, to access them we will have to call the function twice.
dictionary = {key_value_creator(item)['key']: \
key_value_creator(item)['value'] for item in sample_list}
dictionary = {key_value_creator(item)[0]: \
key_value_creator(item)[1] for item in sample_list}
Is there a way to format these values so that we can send them to the dictionary comprehension statement in the format that it requires?
EDIT:
Expected Output:
{ 'John': {'age': '24', 'gender': 'M', 'lang': 'English'},
'Jeanne': {'age': '21', 'gender': 'F', 'lang': 'French'},
'Yuhanna': {'age': '22', 'gender': 'M', 'lang': 'Arabic'}}
Just use the dict builtin function, expecting a sequence of (key, value) pairs as returned by your key_value_creator function and making a dict from those:
>>> dict(map(key_value_creator, sample_list))
{'Jeanne': {'age': '21', 'gender': 'F', 'lang': 'French'},
'John': {'age': '24', 'gender': 'M', 'lang': 'English'},
'Yuhanna': {'age': '22', 'gender': 'M', 'lang': 'Arabic'}}
Also works with a generator expression instead of map:
>>> dict(key_value_creator(item) for item in sample_list)
Or use a dictionary comprehension with a nested generator expression and tuple-unpacking:
>>> {k: v for k, v in (key_value_creator(item) for item in sample_list)}
Or without your key_value_creator function, just using a nested dictionary comprehension:
>>> {n: {"age": a, "gender": g, "lang": l} for n, a, g, l in sample_list}
I have a nested dictionary:
d = { 'wing': {'name': 'Ali', 'age': '19'},
'scrumHalf': {'name': 'Bob', 'age': '25'},
'flyHalf': {'name': 'Sam', 'age': '43'},
'prop': {'name': 'rob', 'age': '33'}}
I want to pull out the values for age only to generate a list
[19, 25, 43, 33]
I want to do this using a for loop, and as naively as possible, as I usually find that easiest to understand.
I have managed to print all of the keys using a for loop:
for i in d:
print i
for j in d[i]:
print j
but when I tried to edit it to print the values I got the error
NameError: name 'value' is not defined. How can I get 'value' to mean the value attached to a key?
Here is my edited version
for i in d:
print (i[value])
for j in d[i]:
print (j[value])
I am using python 2.7
You can access values in the dict with the help of the method values():
[i['age'] for i in d.values()]
# ['19', '25', '43', '33']
>>> [d.get(k).get('age') for k, v in d.items()]
['33', '25', '19', '43']
In-order to access a dictionary's value you are iterating through keys first which is correct i.e. for i in d:. So, in order to access value of key i in d, you'll need to do d[i] which will give you the value, for example {'name': 'rob', 'age': '33'} then to access the required key you'll have to access from dictionary once more i.e. d[i]['age'].
I'm new to Python and I'm still learning how to use. I have the follow dictionary:
dic = {'0': {'text': 'a', 'lang': 'es', 'rating': '4'}, '1': {'text': 'b', 'lang': 'es', 'rating': '3'}, '2': {'text': 'c', 'lang': 'es', 'rating': '1'}, '3': {'text': 'd', 'lang': 'es', 'rating': '2'}, '4': {'text': 'e', 'lang': 'es', 'rating': '5'}}
Now, I'm trying to know if the text, for example, 'a' is a value of any of those nested dictionaries (I know there is a value() function which returns the values of the dictionaries, but in this case it will only return the values of the first dictionary, won't it? Like 0,1,2,3,4)
I tried
for i in range(len(dic)):
if text in dic[i].values():
print("Yes")
else:
print("No")
But this gives me a KeyError with value '0'. I have searched for similar questions, but haven't found any which I can use to solve my problem. Can you please help me? Thanks in advance.
You can use any:
dic = {'0': {'text': 'a', 'lang': 'es', 'rating': '4'}, '1': {'text': 'b', 'lang': 'es', 'rating': '3'}, '2': {'text': 'c', 'lang': 'es', 'rating': '1'}, '3': {'text': 'd', 'lang': 'es', 'rating': '2'}, '4': {'text': 'e', 'lang': 'es', 'rating': '5'}}
result = any('a' in d.values() for d in dic.values())
You can use any with a generator comprehension, as suggested by #Ajax1234.
Or, if you do this repeatedly, you can calculate a set of values and check for membership with O(1) complexity. itertool.chain is a useful tool to combine nested values:
from itertools import chain
values = set(chain.from_iterable(i.values() for i in dic.values()))
res = 'a' in values # True
Starting first from what you have tried, you could indeed:
Use a for loop to iterate over the values of dic, that are dictionaries too.
Check inside each dictionary if the value of the key 'text' equals 'a'.
If yes, then print 'Yes' and stop the loop.
If the loop ends without any match, then print 'No'.
Let's do it with a beautiful for/else statement:
for d in dic.values():
if d['text'] == 'a':
print("Yes")
break
else:
print("No")
To go further, you could also:
use comprehension to perform the for loop and the == operation in a smarter Python way,
and use any to replace the if and break statements by a smarter Python built-in function.
This shorter code will in fact do exactly the same things as previous one, in a really pythonic way:
if any(d['text'] == 'a' for d in dic.values()):
print("Yes")
else:
print("No")
Enjoy !
if you are sure that the string you are looking for will no be in key names, then another simple solution is converting whole dict to str and searching for string
if 'a' in str(dic):
print("a is there")
You are treating the dictionary as a list. You cannot index into a dictionary, like this:
dic[0]
But you can get the value from a given key, like so:
dic["0"] # yields {'text': 'a', 'lang': 'es', 'rating': '4'}
As such, modify your for loop as follows:
for i in dic:
...
I have a dictionary with missing values (the key is there, but the associated value is empty). For example I want the dictionary below:
dct = {'ID':'', 'gender':'male', 'age':'20', 'weight':'', 'height':'5.7'}
to be changed to this form:
dct = {'ID':NaN, 'gender':'male', 'age':'20', 'weight':NaN, 'height':'5.7'}
How can I write that in the most time-efficient way?
You can use a dictionary comprehension. Also as was noted in the comments, naming something dict in Python is not good practice.:
dct = {'ID':'', 'gender':'male', 'age':'20', 'weight':'', 'height':'5.7'}
dct = {k: None if not v else v for k, v in dct.items() }
print(dct)
Output:
{'ID': None, 'gender': 'male', 'age': '20', 'weight': None, 'height': '5.7'}
Just replace None with whatever you want it to default to.
In your question, you want to replace with NaN.
You can use any of the following:
float('nan') if you are using Python 2.x, or with Python <3.5
math.nan for Python 3.5+
numpy.nan using numpy
You can use implicit syntax with boolean or expression:
In [1]: dct = {'ID':'', 'gender':'male', 'age':'20', 'weight':'', 'height':'5.7'}
In [2]: {k: v or None for k, v in dct.items()}
Out[2]: {'ID': None, 'age': '20', 'gender': 'male', 'height': '5.7', 'weight': None}
But be aware that in The Zen of Python it's said:
Explicit is better than implicit.
You can create a class object to represent NaN:
class NaN:
def __init__(self, default=None):
self.val = default
def __repr__(self):
return 'NaN'
dct = {'ID':'', 'gender':'male', 'age':'20', 'weight':'', 'height':'5.7'}
new_d = {a:NaN() if not b else b for a, b in dct.items()}
Output:
{'gender': 'male', 'age': '20', 'ID': NaN, 'weight': NaN, 'height': '5.7'}
You can use a for loop to iterate over all of they keys and values in the Dictionary.
dct = {'ID': '', 'gender': 'male', 'age': '20', 'weight': '', 'height': '5.7'}
for key, value in dct.items():
if value == '':
dct[key] = 'NaN'
print(dct)
You created your dictionary with a series of key value pairs.
I used a for loop and the .items() method to iterate over each key value pair in your dictionary.
if the value of the key/value pair is an empty string, We change the that particular value to 'NaN' and leave the rest unchanged.
When we print the new dictionary we get this output:
{'ID': 'NaN', 'gender': 'male', 'age': '20', 'weight': 'NaN', 'height': '5.7'}
This is time efficient because it is a quick loop, so long as you are okay with not 'NaN' values being strings. I am not sure if you are looking for them to be strings, however, you can change the value from 'NaN' to None very simply if that is what you are looking for. The for loop is relatively efficient in terms of time since it will iterate over each value quickly.