python dictionaries within a list - python

I have the below dictionaries within a list:
price_list = [
{'id': 1, 'name': 'apple', 'price': '100', 'year': '2000', 'currency': 'eur'},
{'id': 2, 'name': 'apple', 'price': '150', 'year': '2022', 'currency': 'eur'},
{'id': 3, 'name': 'apple', 'price': '1220', 'year': '160', 'currency': 'eur'},
{'id': 4, 'name': 'apple', 'price': '150', 'year': '2080', 'currency': 'eur'}
]
The below code calculates the average price of the list:
for d in price_list:
for _,item in d.items():
total += int(d['price'])
count += 1
print(total,count)
print('average=', total / count)
I want to be able to ignore anything within 10 years of the mid. So if i had an input of year = 2020, when querying against my list i will only want search back to 2010 and anything forward to 2030. Is this possible to implement?

Look up the year and test it for the year range, then if it is an 'apple' then add the price so you calculate the average.
l = [{'id': 1, 'name': 'apple', 'price': '100', 'year': '2000', 'currency': 'eur'}, {'id': 2, 'name': 'apple', 'price': '150', 'year': '2022', 'currency': 'eur'}, {'id': 3, 'name': 'apple', 'price': '1220', 'year': '160', 'currency': 'eur'}, {'id': 4, 'name': 'apple', 'price': '150', 'year': '2080', 'currency': 'eur'}]
mid_year = 2020
total = 0
count = 0
for d in l:
if int(d['year']) >= mid_year-10 and int(d['year']) <= mid_year+10:
if d['name'] == 'apple':
total += int(d['price'])
count += 1
print('average=', total / count)
Runnable code: https://trinket.io/python3/1ab1232e44

You can use a short for to make it one line
price = [int(d['price']) for d in price_list if int(d['year'])>year-10 and int(d['year'])<year+10]
print('average=', sum(price)/len(price)

Related

How to sort a List in Python on variable number of parameters [duplicate]

This question already has answers here:
How to sort objects by multiple keys?
(8 answers)
Closed 2 months ago.
I have a list of dictionaries, that I have to sort. However, the key/parameter on which to sort will be determined dynamically. The way this is done is I will create a method which will take the list and sorting columns as input as follows:
def processList(l, sortId= None):
<logic>
return l
Here's an example:
I have 5 dictionaries in a list:
[
{'name': 'alpha', 'price': 200, 'date': '2022-02-01'},
{'name': 'beta', 'price': 400, 'date': '2022-03-01'},
{'name': 'delta', 'price': 500, 'date': '2022-05-01'},
{'name': 'zeta', 'price': 400, 'date': '2022-02-10'},
{'name': 'kappa', 'price': 500, 'date': '2022-01-31'}
]
Now, I wish to sort it, but sorting criteria can be determined at runtime. So I can have sorting done by name and the output will be:
>>> l.sort(key=lambda x:x['name'])
[
{'name': 'alpha', 'price': 200, 'date': '2022-02-01'},
{'name': 'beta', 'price': 400, 'date': '2022-03-01'},
{'name': 'delta', 'price': 500, 'date': '2022-05-01'},
{'name': 'kappa', 'price': 500, 'date': '2022-01-31'},
{'name': 'zeta', 'price': 400, 'date': '2022-02-10'}
]
or sort by price and date:
>>> l.sort(key=lambda x:(x['price'], x['date']))
[
{'name': 'alpha', 'price': 200, 'date': '2022-02-01'},
{'name': 'zeta', 'price': 400, 'date': '2022-02-10'},
{'name': 'beta', 'price': 400, 'date': '2022-03-01'},
{'name': 'kappa', 'price': 500, 'date': '2022-01-31'},
{'name': 'delta', 'price': 500, 'date': '2022-05-01'}
]
I can't loop in over all the sorting columns because in the next iteration, it will rearrange/sort the data with respect to that column.
Is there a way to unpack the keys within lambda?
You can easily use custom list comprehension to write it like this:
l = sorted(l, key=lambda x: [ x[col] for col in sortId])

Remove duplicates from list of lists by column value

I have a list of list that look like this, they have been sorted so that duplicate IDs are arranged with the one I want to keep at the top..
[
{'id': '23', 'type': 'car', 'price': '445'},
{'id': '23', 'type': 'car', 'price': '78'},
{'id': '23', 'type': 'car', 'price': '34'},
{'id': '125', 'type': 'truck', 'price': '998'},
{'id': '125', 'type': 'truck', 'price': '722'},
{'id': '125', 'type': 'truck', 'price': '100'},
{'id': '87', 'type': 'bike', 'price': '50'},
]
What is the simplest way to remove rows that have duplicate IDs but always keep the first one? In this instance the end result would look like this...
[
{'id': '23', 'type': 'car', 'price': '445'},
{'id': '125', 'type': 'truck', 'price': '998'},
{'id': '87', 'type': 'bike', 'price': '50'},
]
I know I can remove duplicates from lists by converting to set like set(my_list) but in this instance it is duplicates by ID that I want to remove by
Since you already hav the list sorted properly, a simple way to do this is to use itertools.groupby to grab the first element of each group in a list comprehension:
from itertools import groupby
l= [
{'id': '23', 'type': 'car', 'price': '445'},
{'id': '23', 'type': 'car', 'price': '78'},
{'id': '23', 'type': 'car', 'price': '34'},
{'id': '125', 'type': 'truck', 'price': '998'},
{'id': '125', 'type': 'truck', 'price': '722'},
{'id': '125', 'type': 'truck', 'price': '100'},
{'id': '87', 'type': 'bike', 'price': '50'},
]
[next(g) for k, g in groupby(l, key=lambda d: d['id'])]
# [{'id': '23', 'type': 'car', 'price': '445'},
# {'id': '125', 'type': 'truck', 'price': '998'},
# {'id': '87', 'type': 'bike', 'price': '50'}]
I would probably convert to Pandas DataFrame and then use drop_duplicates
import pandas as pd
data = [
{'id': '23', 'type': 'car', 'price': '445'},
{'id': '23', 'type': 'car', 'price': '78'},
{'id': '23', 'type': 'car', 'price': '34'},
{'id': '125', 'type': 'truck', 'price': '998'},
{'id': '125', 'type': 'truck', 'price': '722'},
{'id': '125', 'type': 'truck', 'price': '100'},
{'id': '87', 'type': 'bike', 'price': '50'},
]
df = pd.DataFrame(data)
df.drop_duplicates(subset=['id'], inplace=True)
print(df.to_dict('records'))
# Output
# [{'id': '23', 'type': 'car', 'price': '445'},
# {'id': '125', 'type': 'truck', 'price': '998'},
# {'id': '87', 'type': 'bike', 'price': '50'}]
Here's an answer that involves no external modules or unnecessary manipulation of the data:
data = [
{'id': '23', 'type': 'car', 'price': '445'},
{'id': '23', 'type': 'car', 'price': '78'},
{'id': '23', 'type': 'car', 'price': '34'},
{'id': '125', 'type': 'truck', 'price': '998'},
{'id': '125', 'type': 'truck', 'price': '722'},
{'id': '125', 'type': 'truck', 'price': '100'},
{'id': '87', 'type': 'bike', 'price': '50'},
]
seen = set()
result = [row for row in data if row['id'] not in seen and not seen.add(row['id'])]
print(result)
Result:
[{'id': '23', 'type': 'car', 'price': '445'},
{'id': '125', 'type': 'truck', 'price': '998'},
{'id': '87', 'type': 'bike', 'price': '50'}]
Note that the not seen.add(row['id'])] part of the list comprehension will always be True. It's just a way of noting that a unique entry has been seen by adding it to the seen set.
Let's take the name of the given list as data.
unique_ids = []
result = []
for item in data:
if item["id"] not in unique_ids:
result.append(item)
unique_ids.append(item["id"])
print(result)
The result will be,
[{'id': '23', 'type': 'car', 'price': '445'},
{'id': '125', 'type': 'truck', 'price': '998'},
{'id': '87', 'type': 'bike', 'price': '50'}]

Find duplicate values in list of dicts and summarize other relevand values

I have list of dicts with product info. I need to summarize price field for the same products and to get the result in the same format.
I have:
data = [
{'title': 'Apple', 'price': '200'},
{'title': 'Apple', 'price': '300'},
{'title': 'Apple', 'price': '400'},
{'title': 'Samsung', 'price': '250'},
{'title': 'Sony', 'price': '100'}
]
I need:
data = [
{'title': 'Apple', 'price': '900'},
{'title': 'Samsung', 'price': '250'},
{'title': 'Sony', 'price': '100'}
]
itertools.groupby:
[
{'title': k, 'price': str(sum(int(i['price']) for i in g))}
for k, g in itertools.groupby(data, key=lambda x: x['title'])
]
for k, g in itertools.groupby(data, key=lambda x: x['title']) iterates over the key-group created by grouping data on title
{'title': k, 'price': str(sum(int(i['price']) for i in g))} is a dict comprehension with the price value created by iterating over the groups and summing the prices
Example:
In [472]: data = [
...: {'title': 'Apple', 'price': '200'},
...: {'title': 'Apple', 'price': '300'},
...: {'title': 'Apple', 'price': '400'},
...: {'title': 'Samsung', 'price': '250'},
...: {'title': 'Sony', 'price': '100'}
...: ]
In [473]: [{'title': k, 'price': str(sum(int(i['price']) for i in g))} for k, g in itertools.groupby(data, key=lambda x: x['title'])]
Out[473]:
[{'title': 'Apple', 'price': '900'},
{'title': 'Samsung', 'price': '250'},
{'title': 'Sony', 'price': '100'}]
If the input is not soorted, you need to sort it first based on the title key i.e:
sorted(data, key=lambda x: x['title'])
use this:
data = [
{'title': 'Apple', 'price': '200'},
{'title': 'Apple', 'price': '300'},
{'title': 'Apple', 'price': '400'},
{'title': 'Samsung', 'price': '250'},
{'title': 'Sony', 'price': '100'}
]
price = {}
for row in data:
if row['title'] not in price:
price[row['title']] = 0
price[row['title']] += int(row['price'])
data = []
for title in price:
data.append({'title': title, 'price': str(price[title])})
print(data);

How to get/filter values in python3 json list dictionary response?

Below is result I got from API query.
[{'type':'book','title': 'example1', 'id': 12456, 'price': '8.20', 'qty': '12', 'status': 'available'},
{'type':'book','title': 'example2', 'id': 12457, 'price': '10.50', 'qty': '5', 'status': 'none'}]
How do I specify in code to get value pairs of title, price, & status only?
So result will be like:
[{'title': 'example1', 'price': '8.20', 'status': 'available'},
{'title': 'example2', 'price': '10.50', 'status': 'none'}]
You can use a dictionary comprehension within a list comprehension:
L = [{'type':'book','title': 'example1', 'id': 12456, 'price': '8.20', 'qty': '12', 'status': 'available'},
{'type':'book','title': 'example2', 'id': 12457, 'price': '10.50', 'qty': '5', 'status': 'none'}]
keys = ['title', 'price', 'status']
res = [{k: d[k] for k in keys} for d in L]
print(res)
[{'price': '8.20', 'status': 'available', 'title': 'example1'},
{'price': '10.50', 'status': 'none', 'title': 'example2'}]

Python dictionary value conversion to dictionary list

class Weightcheck:
def bag_products(self,product_list):
bag_list = []
non_bag_items = []
MAX_BAG_WEIGHT = 5.0
for product in product_list:
if float(product['weight']) > MAX_BAG_WEIGHT:
product_list.remove(product)
non_bag_items.append(product)
and argument product_list is like
product_list = {'barcode': [123, 456], 'Name': ['Milk, 2 Litres', 'Bread'], 'Price': ['2', '3.5'], 'weight': ['2', '0.6']}
if the passed arugument is like
product_list = [{'name': 'Milk', 'price': 2.0, 'weight': 2.0},
{'name': 'LowfatMilk', 'price': 2.0, 'weight': 2.0},
{'name': 'HighfatMilk', 'price': 2.0, 'weight': 2.0},
{'name': 'Bread', 'price': 2.0, 'weight': 7.0}]
then it works properly. i mean list of dictionary. please help how can i solve this
This is not the best way but you can use something like this:
final_list = []
for i in range(len(product_in_basket['Name'])):
item ={} # each new item
for k,v in product_in_basket.items():
item[k]= v[i] # filling that item with specific index
final_list.append(item) # append to final list
> final_list
[
{'Name': 'Milk, 2 Litres', 'Price': '2', 'barcode': 123, 'weight': '2.0'},
{'Name': 'Bread', 'Price': '3.5', 'barcode': 456, 'weight': '0.6'}
]
Here's a one-liner that does the trick:
product_list = [dict(zip(product_in_basket,t)) for t in zip(*product_in_basket.values())]
print(product_list)
Output:
[{'Name': 'Milk, 2 Litres', 'Price': '2', 'barcode': 123, 'weight': '2.0'}, {'Name': 'Bread', 'Price': '3.5', 'barcode': 456, 'weight': '0.6'}]
In general, it's better to not use a library when plain Python will do, but I thought a solution using pandas might be interesting:
import pandas as pd
product_in_basket = {'barcode': [123, 456], 'Name': ['Milk, 2 Litres', 'Bread'],
'Price': ['2', '3.5'], 'weight': ['2.0', '0.6']}
df = pd.DataFrame(product_in_basket)
output = list(df.T.to_dict().values())
print(output)
Output:
[{'Name': 'Milk, 2 Litres', 'Price': '2', 'barcode': 123, 'weight': '2.0'},
{'Name': 'Bread', 'Price': '3.5', 'barcode': 456, 'weight': '0.6'}]

Categories