I'm trying to create a dictionary of specific key values from a list of dictionaries. I believe my code is not flattening out the dictionaries when i put in chunkdata.extend(pythondict[0][1][2], chunkdata will return with the whole 1st 2nd and 3rd dictionaries where i want something like the "name" key pair for all the dictionaries that return in the response.
chunkdata = []
for chunk in chunklist:
url3 = "some URL"
headers = {'accept': 'application/json',
response = requests.request("GET", url3, headers=headers)
time.sleep(5)
print(response.text)
pythondict = json.loads(response.text)
print(pythondict)
chunkdata.extend(pythondict['name']['age']['date']
pythondict output
[{'data': {'name': 'jon', 'age': '30', 'date': '2020-01-05', 'time': '1', 'color': 'blue'}, {'data': {'name': 'phil', 'age': '33', 'date': '2020-01-05', 'time': '1', 'color': 'blue'}, {'data': {'name': 'ted', 'age': '25', 'date': '2020-01-05', 'time':'1', 'color': 'blue'}]
Traceback (most recent call last):
File line 84, in <module>
chunkdata.extend(pythondict['name']['age']['date']
TypeError: list indices must be integers or slices, not str
Use requests.json() for parsing. It is more reliable and accurate.
Note: Response header MUST contain Content-Type: application/json in the header in order for .json() method to work
I figured out that the json format you get is not right here. I was not able to make out the necessity of the 'data:' prior to each element.
It would be better to modify it in the following form:
python_dict=[{'name': 'jon', 'age': '30', 'date': '2020-01-05', 'time': '1', 'color': 'blue'}, {'name': 'phil', 'age': '33', 'date': '2020-01-05', 'time': '1', 'color': 'blue'}, {'name': 'ted', 'age': '25', 'date': '2020-01-05', 'time':'1', 'color': 'blue'}]
Modify the relevant part of the code as follows:
chunkdata=[]
for x in range(len(python_dict)):
temp_list=[python_dict[x]['name'],python_dict[x]['age'],python_dict[x]['date'],python_dict[x]['time'],python_dict[x]['color']]
chunkdata.append(temp_list)
print(chunkdata)
chunkdata will be a list of lists that you can keep appending into. The output for chunkdata is as follows:
[['jon', '30', '2020-01-05', '1', 'blue'], ['phil', '33',
'2020-01-05', '1', 'blue'], ['ted', '25', '2020-01-05', '1', 'blue']]
Related
I’m working with a CSV file that looks as follows:
POS,Transaction id,Product,Quantity,Customer,Date
1,E100,TV,1,Test Customer,9/19/2022
2,E100,Laptop,3,Test Customer,9/20/2022
3,E200,TV,1,Test Customer,9/21/2022
4,E300,Smartphone,2,Test Customer,9/22/2022
5,E300,Laptop,5,New Customer,9/23/2022
6,E300,TV,1,New Customer,9/23/2022
7,E400,TV,2,ABC,9/24/2022
8,E500,Smartwatch,4,ABC,9/25/2022
In order to grab elements out of it this gets each line into a callable line by assignment:
with open(obj.file_name.path, 'r') as f:
rdr = csv.DictReader(f)
for row in rdr:
pos = row['POS']
product = row['Product']
transaction_id = row['Transaction id']
quantity = row['Quantity']
customer = row['Customer']
date = row['Date']
try:
product_obj = Product.objects.get(name__iexact=product)
except Product.DoesNotExist:
product_obj = None
For example to print each row from the CSV I can now type:
pos, transaction_id, product, quantity, customer, transaction_id, date = row
print(row)
Resulting in this terminal output:
file is being uploaded
{'POS': '1', 'Transaction id': 'E100', 'Product': 'TV', 'Quantity': '1', 'Customer': 'Test Customer', 'Date': '9/19/2022'}
{'POS': '2', 'Transaction id': 'E100', 'Product': 'Laptop', 'Quantity': '3', 'Customer': 'Test Customer', 'Date': '9/20/2022'}
{'POS': '3', 'Transaction id': 'E200', 'Product': 'TV', 'Quantity': '1', 'Customer': 'Test Customer', 'Date': '9/21/2022'}
{'POS': '4', 'Transaction id': 'E300', 'Product': 'Smartphone', 'Quantity': '2', 'Customer': 'Test Customer', 'Date': '9/22/2022'}
{'POS': '5', 'Transaction id': 'E300', 'Product': 'Laptop', 'Quantity': '5', 'Customer': 'New Customer', 'Date': '9/23/2022'}
{'POS': '6', 'Transaction id': 'E300', 'Product': 'TV', 'Quantity': '1', 'Customer': 'New Customer', 'Date': '9/23/2022'}
{'POS': '7', 'Transaction id': 'E400', 'Product': 'TV', 'Quantity': '2', 'Customer': 'ABC', 'Date': '9/24/2022'}
{'POS': '8', 'Transaction id': 'E500', 'Product': 'Smartwatch', 'Quantity': '4', 'Customer': 'ABC', 'Date': '9/25/2022'}
So it totally works, what I’m struggling with however is how to access one particular dictionary say I want to only access a particular dictionary, the one containing POS: 1, or to see all dictionaries containing the product TV. How would I go about this?
Edit:
Even though it is possible to extract product, using it in assignment of product_obj it always returns None. Does anyone know what the reason for this might be?
rdr = csv.DictReader(...) is (probably) dynamically creating the entries as it reads them
Either collect them all into a list() and index them at the line you're after [index] or break when you find the line with the content you want
for row in csv.DictReader(...):
if row.get(search_key) == search_value:
break # or return from a function
raise ValueError(f"failed to find {search_key}")
I wasn't able to run your coding on my computer but there are a lot of ways of doing what you are attempting to do. I would recommend:
https://blog.finxter.com/how-to-filter-a-dictionary-in-python/#:~:text=The%20Most%20Pythonic%20Way%29%201%20Method%201%3A%20Simple,4%20Method%204%3A%20Filter%20By%20Dictionary%20Comprehension%20
If possible, I would recommend using pandas.
import pandas as pd
file = "Your file path here"
df = pd.read_csv(file)
#To filter for 1
print(df[df['POS']==1])
#To filter for TV
print(df[df['Product']=='TV'])
I am trying to fetch value of time if found in people it should print time otherwise without time
Below is code which I am trying to test:
import datetime
people = {1: {'time': '', 'age': '27', 'sex': 'Male'},
2: {'time': '', 'age': '22', 'sex': 'Female'}}
time = datetime.datetime.now()
for time in people.items():
if time in people.items():
print(people,"true");
else:
print(people,"false");
The output is :
{1: {'age': '27', 'sex': 'Male', 'time': ''}, 2: {'age': '22', 'sex': 'Female', 'time': ''}} true
{1: {'age': '27', 'sex': 'Male', 'time': ''}, 2: {'age': '22', 'sex': 'Female', 'time': ''}} true
I want it to display the value of current timestamp value in time.
Desired output:
{1: {'age': '27', 'sex': 'Male', 'time': '2021-06-17T05:42:32.204965'}, 2: {'age': '22', 'sex': 'Female', 'time': '2021-06-17T05:42:32.204965'}} true
Refrence:
{
"id": "urn:ngsi-ld:Device:filling001",
"type": "FillingSensor",
"filling": {
"type": "Property",
"value": 0.94,
"unitCode": "C62",
**"time": "2021-01-28T12:33:10.000Z"**
},
"time_index": "2021-01-28T12:33:20.476"
}
What i am doing wrong here. help on this will be great?
There are several problems with your code :
You use the same variable time with time = datetime.datetime.now() and for time in people.items() so the second will overwrite the first one value.
people.items() returns a tuple of key, value elements, ie: (1, {...}) so you cannot compare time with (key, value).
Using in operator for this seems quite wrong to me, I would try something like below.
.
time = datetime.datetime.now()
for key, val in people.items():
print({key:val}, "true" if val.get("time") == time else "false")
You need to initialize time as datetime.datetime.now() before the dictionary initialization, and then replace the empty quotes with time.
the following is a subset of a really large nested dictionary that I have:
{
'1': {'Name': 'Katherine Watson',
'Age': '1',
'Height': '150'},
'2': {'Name': 'Emilia Li',
'Age': '56',
'Height': '175'},
'3': {'Name': 'Dorothy Johnson',
'Age': '29',
'Height': '162'},
'4': {'Name': 'Alexandar Knight',
'Age': '14',
'Height': '164r'}
}
I'm having trouble figuring out how to write a function that will iterate through the specific key ('Height'), which then returns the corresponding value if it's all numerical numbers or None otherwise.
E.g. the dictionary with ID'1' should return '150' for the height. But the dictionary with ID'4' should return None for the height.
Here's a code I've written but it only returns '150' instead of iterating through all the IDs and returning '150' '175' '162' 'None'.
data = {
'1': {'Name': 'Katherine Watson',
'Age': '1',
'Height': '150'},
'2': {'Name': 'Emilia Li',
'Age': '56',
'Height': '175'},
'3': {'Name': 'Dorothy Johnson',
'Age': '29',
'Height': '162'},
'4': {'Name': 'Alexandar Knight',
'Age': '14',
'Height': '164r'}
}
def person_height(height):
for some_id, info in data.items():
if info['Height'].isnumeric():
return info['Height']
else:
return None
Use isdigit
data = {
'1': {'Name': 'Katherine Watson',
'Age': '1',
'Height': '150'},
'2': {'Name': 'Emilia Li',
'Age': '56',
'Height': '175'},
'3': {'Name': 'Dorothy Johnson',
'Age': '29',
'Height': '162'},
'4': {'Name': 'Alexandar Knight',
'Age': '14',
'Height': '164r'}
}
def person_height(height):
if height.isdigit():
return height
for some_id, info in data.items():
print("\nID:", some_id)
print("Height:", person_height(info['Height']))
Output:
ID: 1
Height: 150
ID: 2
Height: 175
ID: 3
Height: 162
ID: 4
Height: None
You could also do this with a list comprehension.
def get_heights(data):
return [int(person['Height'])
if person['Height'].isdigit()
else None
for person in data.values()]
print(get_heights(data))
Running it with your sample data outputs:
[150, 175, 162, None]
Since you're not using the IDs, you can use .values() instead of .items(). And in your code, you named the argument height but then refer to data in the function body. This means that it doesn't matter what you supply as the argument; the code only works because it's referring back to the globally defined variable, which happens to have the same name.
I've also converted the heights to integers, even though you didn't specifically request that.
Your code is fine actually but return will break the loop immediately and return the first result only so just turn your return to print() will do the work.
Another way is save the result to a list first and read them later:
data = {
'1': {'Name': 'Katherine Watson',
'Age': '1',
'Height': '150'},
'2': {'Name': 'Emilia Li',
'Age': '56',
'Height': '175'},
'3': {'Name': 'Dorothy Johnson',
'Age': '29',
'Height': '162'},
'4': {'Name': 'Alexandar Knight',
'Age': '14',
'Height': '164r'}
}
def person_height(data):
height_list = []
for some_id, info in data.items():
if info['Height'].isnumeric():
height_list.append(info['Height'])
else:
height_list.append(None)
return height_list
for height in person_height(data):
print(height)
Output:
150
175
162
None
In order to store your results in a "clean" dictionary, you will need as many nested loops as nested dictionaries you have. So:
def check_height(your_dict):
new_clean_dict = {}
for a, b in your_dict.items():
for e, f in b.items():
if e == 'Height' and f.isdigit():
new_clean_dict[a] = {'Height': f}
else:
new_clean_dict[a] = {'Height': None}
return new_clean_dict
This will produce a new dictionary with the same root key and with a value for each key that is a nested dictionary with only the key Height.
In order to get the results:
new_clean_dict = check_height(your_dict)
I'm a newbie in Python. I have a list of members and a list of meetings (containing the member id):
memberList = [{'id': '1', 'name': 'Joe'},
{'id': '2', 'name': 'Jason'},
{'id': '3', 'name': 'Billy'}]
meetingList = [{'meetingId': '20', 'hostId' : '1'},
{'meetingId': '21', 'hostId' : '1'},
{'meetingId': '22', 'hostId' : '2'},
{'meetingId': '23', 'hostId' : '2'}]
Where the id of the member and the hostId of meeting is the same value.
Result: a list of member ids which has no meetings ['3'] or the list of dicts [{'id': '3', 'name': 'Billy'}]
What's the best and most readable way to do it?
You could build a set of hosts and then use a list comprehension to filter out the members:
member_list = [{'id': '1', 'name': 'Joe'},
{'id': '2', 'name': 'Jason'},
{'id': '3', 'name': 'Billy'}]
meeting_list = [{'meetingId': '20', 'hostId': '1'},
{'meetingId': '21', 'hostId': '1'},
{'meetingId': '22', 'hostId': '2'},
{'meetingId': '23', 'hostId': '2'}]
# create a set of hosts
hosts = set(meeting['hostId'] for meeting in meeting_list) # or { meeting['hostId'] for meeting in meeting_list }
# filter out the members that are in hosts
res = [member['id'] for member in member_list if member['id'] not in hosts]
print(res)
Output
[{'id': '3', 'name': 'Billy'}]
For the id only output, do:
res = [member['id'] for member in member_list if member['id'] not in hosts]
print(res)
Output
['3']
I'd extract out the id's from both lists of dictionaries and compare them directly.
First I'm just rewriting your list variables to assign them with =.
Using : won't save the variable.
memberList = [{'id': '1', 'name': 'Joe'},
{'id': '2', 'name': 'Jason'},
{'id': '3', 'name': 'Billy'}]
meetingList = [{'meetingId': '20', 'hostId' : '1'},
{'meetingId': '21', 'hostId' : '1'},
{'meetingId': '22', 'hostId' : '2'},
{'meetingId': '23', 'hostId' : '2'}]
Then use list comprehension to extract out the id's from each list of dicts.
member_id_list = [i["id"] for i in memberList]
meeting_hostid_list = [i["hostId"] for i in meetingList]
You could also use list comprehension here but if you aren't familiar with it, this for loop and if logic will print out any member id who isn't a host.
for i in member_id_list:
if i not in meeting_hostid_list:
print(i)
>> 3
I am trying to update a specific key in python but it appears that all the keys that are similar are also updated.
inner_dict = {'grade': None, 'age': None, 'genre': None}
outer_dict = {'Sam': inner_dict, 'Joe': inner_dict, 'Some' : inner_dict}
outer_dict['Sam']['age'] = 10
I expect to have this as an output:
{'Sam': {'grade': None, 'age': 10, 'genre': None}, 'Joe': {'grade': None, 'age': None, 'genre': None}, 'Some': {'grade': None, 'age': None, 'genre': None}}
But instead I have this:
{'Sam': {'grade': None, 'age': 10, 'genre': None}, 'Joe': {'grade': None, 'age': 10, 'genre': None}, 'Some': {'grade': None, 'age': 10, 'genre': None}}
in which the ages for all the kids are updated to 10
You have to copy the object, otherwise you have only one single object with 3 references to them.
So the solution is:
outer_dict = {'Sam': inner_dict.copy(), 'Joe': inner_dict.copy(), 'Some' : inner_dict.copy()}
Because you define the dict using the same inner dict 3 times, the three are all references to the same dict; modifying one modifies all three.
This happens because inner_dict is an object and all three are references to the same object. You can fix this by forcing python to create new objects for each entry with the .copy() method:
inner_dict = {'grade': None, 'age': None, 'genre': None}
outer_dict = {'Sam': inner_dict.copy(), 'Joe': inner_dict.copy(), 'Some' : inner_dict.copy()}
outer_dict['Sam']['age'] = 10