Python - Search in a dictionary - python

I need to look for a specific value within a variable.
market = {'fruit': [{'fruit_id': '25', 'fruit': 'banana', weight: 1.00}, {'fruit_id': '15', 'fruit': 'apple', weight: 1 .50}, {'fruit_id': '5', 'fruit': 'pear', weight: 2.00}]}
#print(type(market))
<class 'dict'>
How can I find the fruit whose fruit_id is '15'?

You can iterate over the value of fruit from markets dict and search.
for fr in market['fruit']:
if fr['fruit_id'] == '15':
ans = fr
print(ans)
ans = {'fruit_id': '15', 'fruit': 'apple', 'weight': 1.50}

In addition to the comments, you can create a function to search in your market dictionary:
market = {'fruit': [{'fruit_id': '25', 'fruit': 'banana', 'weight': 1.0},
{'fruit_id': '15', 'fruit': 'apple', 'weight': 1.5},
{'fruit_id': '5', 'fruit': 'pear', 'weight': 2.0}]}
def search_by_id(fruit_id):
for fruit in market['fruit']:
if fruit['fruit_id'] == fruit_id:
return fruit['fruit']
How to use it:
>>> search_by_id('15')
'apple'
>>> search_by_id('5')
'pear'

If you will need to search for fruits by id more than once, consider creating a dict where the id is the key:
>>> market = {'fruit': [
... {'fruit_id': '25', 'fruit': 'banana', 'weight': 1.00},
... {'fruit_id': '15', 'fruit': 'apple', 'weight': 1.50},
... {'fruit_id': '5', 'fruit': 'pear', 'weight': 2.00}
... ]}
>>>
>>> fruits_by_id = {f['fruit_id']: f for f in market['fruit']}
>>> fruits_by_id['15']
{'fruit_id': '15', 'fruit': 'apple', 'weight': 1.5}
Once you have a dict where a particular piece of data is the key, locating that piece of data by the key is easy, both for you and the computer (it's "constant time", aka effectively instantaneous, to locate an item in a dict by its key, whereas iterating through an entire dict takes an amount of time depending on how big the dict is).
If you aren't constrained in how market is defined, and your program is going to be looking up items by their id most of the time, it might make more sense to simply make market['fruit'] a dict up front (keyed on id) rather than having it be a list. Consider the following representation:
>>> market = {'fruit': {
... 25: {'name': 'banana', 'weight': 1.00},
... 15: {'name': 'apple', 'weight': 1.50},
... 5: {'name': 'pear', 'weight': 2.00}
... }}
>>> market['fruit'][15]
{'name': 'apple', 'weight': 1.5}

Related

Dictionary list/dict comparison

I would really appreciate any help on the below. I am looking to create a set of values with 1 name compiling all duplicates, with a second dict value to total another value from a list of dicts. i have compiled the below code as an example:
l = [{'id': 1, 'name': 'apple', 'price': '100', 'year': '2000', 'currency': 'eur'},
{'id': 2, 'name': 'apple', 'price': '150', 'year': '2071', 'currency': 'eur'},
{'id': 3, 'name': 'apple', 'price': '1220', 'year': '2076', 'currency': 'eur'},
{'id': 4, 'name': 'cucumber', 'price': '90000000', 'year': '2080', 'currency': 'eur'},
{'id': 5, 'name': 'pear', 'price': '1000', 'year': '2000', 'currency': 'eur'},
{'id': 6, 'name': 'apple', 'price': '150', 'year': '2022', 'currency': 'eur'},
{'id': 9, 'name': 'apple', 'price': '100', 'year': '2000', 'currency': 'eur'},
{'id': 10, 'name': 'grape', 'price': '150', 'year': '2022', 'currency': 'eur'},
]
new_list = []
for d in l:
if d['name'] not in new_list:
new_list.append(d['name'])
print(new_list)
price_list = []
for price in l:
if price['price'] not in price_list:
price_list.append(price['price'])
print(price_list)
The out put i am hoping to achieve is:
[{'name': 'apple'}, {'price': <The total price for all apples>}]
Use a dictionary whose keys are the names and values are the list of prices. Then calculate the averages of each list.
d = {}
for item in l:
d.setdefault(item['name'], []).append(int(item['price']))
for name, prices in d.items()
d[name] = sum(prices)
print(d)
Actually, I thought this was the same as yesterday's question, where you wanted the average. If you just want the total, you don't need the lists. Use a defaultdict containing integers, and just add the price to it.
from collections import defaultdict
d = defaultdict(int)
for item in l:
d[item['name']] += int(item['price'])
print(d)
This method only requires one loop:
prices = {}
for item in l:
prices.update({item['name']: prices.get(item['name'], 0) + int(item['price'])})
print(prices)
Just for fun I decided to also implement the functionality with the item and price dictionaries separated as asked in the question, which gave the following horrendous code:
prices = []
for item in l:
# get indices of prices of corresponding items
price_idx = [n+1 for n, x in enumerate(prices) if item['name'] == x.get('name') and n % 2 == 0]
if not price_idx:
prices.append({'name': item['name']})
prices.append({'price': int(item['price'])})
else:
prices[price_idx[0]].update({'price': prices[price_idx[0]]['price'] + int(item['price'])})
print(prices)
And requires the following function to retrieve prices:
def get_price(name):
for n, x in enumerate(prices):
if n % 2 == 0 and x['name'] == name:
return prices2[n+1]['price']
Which honestly completely defeats the point of having a data structure. But if it answers your question, there you go.
This could be another one:
result = {}
for item in l:
if item['name'] not in result:
result[item['name']] = {'name': item['name'], 'price': 0}
result[item['name']]['price'] += int(item['price'])

How to fetch values from json response in python having a dictionary containing list of dictionary?

I need to fetch a value like, if the animal is dog than i need its id
{'findSomething': [{'Name': 'Andrew', 'id': '321Z4', 'animal': Dog }, {'Name': 'Andrew', 'id': '31Z45', 'animal': Cat }]}
Try this:
data = {'findSomething': [{'Name': 'Andrew', 'id': '321Z4', 'animal': 'Dog' }, {'Name': 'Andrew', 'id': '31Z45', 'animal': 'Cat' }]}
res = [x['id'] for x in data['findSomething'] if x['animal'] == 'Dog']
print(res) #['321Z4']

Searching dict within a list

If I have the following list of items for a shopping store:
shop_list = [{'item': 'apple', 'amount': 10, 'cost': 5},
{'item': 'banana', 'amount': 12, 'cost': 6},
{'item': 'strawberry', 'amount': 8, 'cost': 9}]
So I have several dicts within a list. I want to find out how to get the item dict knowing the item. For example:
def x(item)
#do something to get the dict
print dict
x('apple') #print {'item': 'apple', 'amount': 10, 'cost': 5}
x('banana') #print {'item': 'banana', 'amount': 12, 'cost': 6}
What's the shortest, most efficient way to do this?
If you intend to lookup entries by their 'item', then you should consider having a dict which keys are the 'item' instead of a list of dict.
shop_list = {
'apple': {'amount': 10, 'cost': 5},
'banana': {'amount': 12, 'cost': 6},
'strawberry': {'amount': 8, 'cost': 9}
}
shop_list['banana'] # {'amount': 10, 'cost': 5}
In particular, this makes the lookup O(1) instead of the O(n) required for traversing the list.
If you cannot update the code that generated the original shop_list, then you can transform the already existing data with a dict-comprehension.
formatted_shop_list = {product['item']: product for product in shop_list}
def x(shop_list, item): # remove first parameter if you want to use global variable
for i in shop_list:
if i['item'] == item:
return i
Then, you can call this function as:
>>> todays_shop_list = [{'item': 'apple', 'amount': 10, 'cost': 5},
... {'item': 'banana', 'amount': 12, 'cost': 6},
... {'item': 'strawberry', 'amount': 8, 'cost': 9}]
>>> x(todays_shop_list, 'apple')
{'item': 'apple', 'amount': 10, 'cost': 5}
You can try iterating through the list and just extract the dict that matches your shop item:
def shop_item(shop_list, item):
return next((x for x in shop_list if x['item'] == item), None)
# or next(filter(lambda x: x['item'] == item, shop_list), None)
Which works as follows:
>>> shop_list = [{'item': 'apple', 'amount': 10, 'cost': 5},
... {'item': 'banana', 'amount': 12, 'cost': 6},
... {'item': 'strawberry', 'amount': 8, 'cost': 9}]
>>> shop_item(shop_list, 'apple')
{'item': 'apple', 'amount': 10, 'cost': 5}
>>> shop_item(shop_list, 'grape')
None
The above uses next() with a generator expression to iterate though the list until the condition is met, and returns None if item is not found.
You can try this:
def x(item):
return [elements for elements in shop_list if elements['item'] == item]
x('apple') #print {'item': 'apple', 'amount': 10, 'cost': 5}
x('banana') #print {'item': 'banana', 'amount': 12, 'cost': 6}
This will return the list item if found
[{'amount': 12, 'cost': 6, 'item': 'banana'}]
and if the result is not found an empty list will be returned.

How to get the index of filtered item in list using lambda?

I have a list of fruits [{'name': 'apple', 'qty': 233}, {'name': 'orange', 'qty': '441'}]
When i filter the list for orange using lambda, list(filter(lambda x: x['name']=='orange', fruits)) , i get the right dict but i can not get the index of the dict. Index should be 1 not 0.
How do i get the right index of the filtered item ?
You can use a list comprehension and enumerate() instead:
>>> fruits = [{'name': 'apple', 'qty': 233}, {'name': 'orange', 'qty': '441'}]
>>> [(idx, fruit) for idx, fruit in enumerate(fruits) if fruit['name'] == 'orange']
[(1, {'name': 'orange', 'qty': '441'})]
Like #ChrisRands posted in the comments, you could also use filter by creating a enumeration object for your fruits list:
>>> list(filter(lambda fruit: fruit[1]['name'] == 'orange', enumerate(fruits)))
[(1, {'name': 'orange', 'qty': '441'})]
>>>
Here are some timings for the two methods:
>>> setup = \
"fruits = [{'name': 'apple', 'qty': 233}, {'name': 'orange', 'qty': '441'}]"
>>> listcomp = \
"[(idx, fruit) for idx, fruit in enumerate(fruits) if fruit['name'] == 'orange']"
>>> filter_lambda = \
"list(filter(lambda fruit: fruit[1]['name'] == 'orange', enumerate(fruits)))"
>>>
>>> timeit(setup=setup, stmt=listcomp)
1.0297133629997006
>>> timeit(setup=setup, stmt=filter_lambda)
1.6447856079998928
>>>

Data processing in lists with duplicates in Python

I have two lists: one contains the products and the other one contains their associated prices. The lists can contain an undefined number of products. An example of the lists would be something like:
Products : ['Apple', 'Apple', 'Apple', 'Orange', 'Banana', 'Banana', 'Peach', 'Pineapple', 'Pineapple']
Prices: ['1.00', '2.00', '1.50', '3.00', '0.50', '1.50', '2.00', '1.00', '1.00']
I want to be able to remove all the duplicates from the products list and keep only the cheapest price associated with the unique products in the price list. Note that some products might have the same price (in our example the Pineapple).
The desired final lists would be something like:
Products : ['Apple', 'Orange', 'Banana', 'Peach', 'Pineapple']
Prices: ['1.00', '3.00', '0.50', '2.00', '1.00']
I would like to know the most effective way to do so in Python. Thank you
from collections import OrderedDict
products = ['Apple', 'Apple', 'Apple', 'Orange', 'Banana', 'Banana', 'Peach', 'Pineapple', 'Pineapple']
prices = ['1.00', '2.00', '1.50', '3.00', '0.50', '1.50', '2.00', '1.00', '1.00']
min_prices = OrderedDict()
for prod, price in zip(products, prices):
min_prices[prod] = min(float(price), min_prices.get(prod, float('inf')))
>>> print min_prices.keys(), min_prices.values()
['Apple', 'Orange', 'Banana', 'Peach', 'Pineapple'] [1.0, 3.0, 0.5, 2.0, 1.0]
Probably the simplest way is to take advantage of dictionaries' enforcement of unique keys:
from operator import itemgetter
Products = ['Apple', 'Apple', 'Apple', 'Orange', 'Banana', 'Banana', 'Peach', 'Pineapple', 'Pineapple']
Prices = ['1.00', '2.00', '1.50', '3.00', '0.50', '1.50', '2.00', '1.00', '1.00']
final = dict(sorted(zip(Products, Prices), key=itemgetter(1), reverse=True))
What about this:
prices = map(float,prices)
r={}
for k,v in zip(products,prices):
if v < r.setdefault(k,float('inf')):
r[k] = v
products,prices = r.keys(),map(str,r.values())
Not the shortest solution, but it illustrates the point: Suppose that your lists are products and prices, respectively. Then:
lookup = dict()
for prod, price in zip(products, prices):
if prod not in lookup:
lookup[prod] = price
else:
lookup[prod] = min(price, lookup[prod])
At this point, the lookup dict contains each of your products, and its minimal price. A dict is certainly a better data structure for this than two lists; if you really want to have this as two separate lists instead, you can do something like this:
new_prods = []
new_prices = []
for prod, price in lookup.items():
new_prods.append(prod)
new_prices.append(price)
>>> from collections import OrderedDict
>>> products = ['Apple', 'Apple', 'Apple', 'Orange', 'Banana', 'Banana', 'Peach', 'Pineapple', 'Pineapple']
>>> prices = ['1.00', '2.00', '1.50', '3.00', '0.50', '1.50', '2.00', '1.00', '1.00']
>>> dic = OrderedDict()
>>> for x,y in zip(products,prices):
... dic.setdefault(x, []).append(y)
...
>>> dic.keys()
['Apple', 'Orange', 'Banana', 'Peach', 'Pineapple']
>>> [min(val, key = float) for val in dic.values()]
['1.00', '3.00', '0.50', '2.00', '1.00']
You can use a dictionary to do this:
Products = ['Apple', 'Apple', 'Apple', 'Orange', 'Banana', 'Banana', 'Peach', 'Pineapple', 'Pineapple']
Prices = ['1.00', '2.00', '1.50', '3.00', '0.50', '1.50', '2.00', '1.00', '1.00']
Prices=[float(price) for price in Prices]
di={}
for prod,price in zip(Products,Prices):
di.setdefault(prod,[]).append(price)
for key,val in di.items():
di[key]=min(val)
print di
Prints {'Orange': 3.0, 'Pineapple': 1.0, 'Apple': 1.0, 'Peach': 2.0, 'Banana': 0.5}
If you want two lists in the same order, you can do this:
from collections import OrderedDict
new_prod=OrderedDict.fromkeys(Products).keys()
new_prices=[di[item] for item in new_prod]
Prints:
['Apple', 'Orange', 'Banana', 'Peach', 'Pineapple']
[1.0, 3.0, 0.5, 2.0, 1.0]

Categories

Resources