Get max value index for a list of dicts - python

I'm trying to get the index of the dictionary with the max 'size' in a list of dictionaries like the following:
ld = [{'prop': 'foo', 'size': 100}, {'prop': 'boo', 'size': 200}]
with the following code I can take the maximum size:
items = [x['size'] for x in ld]
print(max(items))
How can I take its index now? Is there an easy way?
Test:
I just figured I can do this:
items = [x['size'] for x in ld]
max_val = max(items)
print(items.index(max_val))
is this correct?

Tell max() how to calculate the maximum for a sequence of indices:
max(range(len(ld)), key=lambda index: ld[index]['size'])
This'll return the index for which the size key is the highest:
>>> ld = [{'prop': 'foo', 'size': 100}, {'prop': 'boo', 'size': 200}]
>>> max(range(len(ld)), key=lambda index: ld[index]['size'])
1
>>> ld[1]
{'size': 200, 'prop': 'boo'}
If you wanted that dictionary all along, then you could just use:
max(ld, key=lambda d: d['size'])
and to get both the index and the dictionary, you could use enumerate() here:
max(enumerate(ld), key=lambda item: item[1]['size'])
Some more demoing:
>>> max(ld, key=lambda d: d['size'])
{'size': 200, 'prop': 'boo'}
>>> max(enumerate(ld), key=lambda item: item[1]['size'])
(1, {'size': 200, 'prop': 'boo'})
The key function is passed each element in the input sequence in turn, and max() will pick the element where the return value of that key function is highest.
Using a separate list to extract all the size values then mapping that back to your original list is not very efficient (you now need to iterate over the list twice). list.index() cannot work as it has to match the whole dictionary, not just one value in it.

You can pass the enumerate(ld) to max function with a proper key :
>>> max(enumerate(ld),key=lambda arg:arg[1]['size'])[0]
1
If you just want the dictionary with max size value, as a Pythonic approach you could use operator.itemgetter function as the key:
In [10]: from operator import itemgetter
In [11]: ld = [{'prop': 'foo', 'size': 100}, {'prop': 'boo', 'size': 200}]
In [12]: fn = itemgetter('size')
In [13]: max(ld, key=fn)
Out[13]: {'prop': 'boo', 'size': 200}

Related

Finding nth biggest value in a nested dictionary

I have been trying to figure out how to return the key which has the nth biggest value in a nested dictionary. What causes problems for me is if there's some missing values like
my_dict = {'0': {'name': 'A', 'price': 50}, '1': {'name': 'B', 'price': 20}, '2': {'name': 'C'}, '3': {'name': 'D', 'price': 10}}
If every price existed, I could use code such as this to get the correct key:
sorted_list = sorted(my_dict.items(), key=lambda item: item[1]['price'])
print(sorted_list[-number_im_using_to_find][1]['name'])
How to account for missing values in an efficient way?
you can use dict.get to achieve this:
get(key[, default])
Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.
Here is a code implementation using dict.get:
default_value = -1
key = lambda item: item[1].get('price', default_value)
sorted_list = sorted(my_dict.items(), key=key)
If you want just sorted values you could remove entirely the index [1]:
default_value = -1
key = lambda value: value.get('price', default_value)
sorted_list = sorted(my_dict.values(), key=key)
EDIT: if you want to be sortable with NoneType in the list, you could use something like:
>>> mylist = [3, 1, None, None, 2, 0]
>>> mylist.sort(key=lambda x: x or -1)
>>> mylist
[None, None, 0, 1, 2, 3]
Use get with a default value, in this case 0 or even a negative value to put the elements with missing prices all the way down the sorted list.
lambda item: item[1].get('price', 0)

How to consolidate only select values in a dictionary with repeated keys

I have a list of dictionaries that contain entries that have the same key for 'name'. I want to merge all dictionaries with duplicate keys while retaining their name value but summing up their weights.
The code below will output:
{'name': ('jake', 'sully', 'jake', 'sully'), 'weight': 2.0}
# Initialising list of dictionary
ini_dict = [{'name': ('jake', 'sully'), 'weight': 1.0}, {'name': ('jake', 'sully'), 'weight': 1.0}]
# printing initial dictionary
print("initial dictionary", str(ini_dict))
# sum the values with same keys
counter = collections.Counter()
for d in ini_dict:
counter.update(d)
result = dict(counter)
print(result)
However that is smashing together the names as well when in reality I am going for:
{'name': ('jake', 'sully), 'weight': 2.0}
How can I achieve this?
You can use a normal dict:
result = {}
for d in ini_dict:
result[d["name"]] = result.get(d["name"], 0) + d["weight"]
The result will be a dict with name as keys and weight as values:
{('jake', 'sully'): 2.0}
If you wanted it back in list form:
lst = [{"name":k, "weight":v} for k, v in result.items()]
The names in the tuple must be in the same order. ('jake', 'sully') != ('sully', 'jake').

sort a list of dictionaries based on explicitly defined order of keys

I have a list of dictionary for ex:
names = [{'Mark':'Volvo'}, {'John':'BMW'}, {'Eliza':'Merci'}, {'Calen':'Audi'}]
I would like to set the explicit ordering by the key names of the dictionary.
For example if I give this order:
['John','Mark','Calen','Eliza']
The expected output would be:
[{'John':'BMW'},{'Mark':'Volvo'},{'Calen':'Audi'},{'Eliza':'Merci'}]
I want to add a custom logic order. To be displayed through the template by their names, based on how I defined the order of their names.
Similar to Is there a way to sort a list of string by a “predicate” list?: Since names is a list of dictionaries with just one key-value pair each, use the index of the person's name in the order list as the key for the sort:
>>> names = [{'Mark': 'Volvo'}, {'John': 'BMW'}, {'Eliza': 'Merci'}, {'Calen' :'Audi'}]
>>> order = ['John', 'Mark', 'Calen', 'Eliza']
>>>
>>> # with `sorted()`
>>> sorted(names, key=lambda d: order.index(list(d.keys())[0]))
[{'John': 'BMW'}, {'Mark': 'Volvo'}, {'Calen': 'Audi'}, {'Eliza': 'Merci'}]
>>>
>>> # or with `list.sort()`
>>> names.sort(key=lambda d: order.index(list(d.keys())[0]))
>>> names
[{'John': 'BMW'}, {'Mark': 'Volvo'}, {'Calen': 'Audi'}, {'Eliza': 'Merci'}]
dict.keys() is not not subscriptable, so dict.keys()[0] doesn't work. So first convert that to a list and then use its one-and-only key list(dict.keys())[0]. That would give 'Mark', 'John', etc. Then get the index of that person's name in the order list. Note: it will fail if a person is not listed in order.
Even if names is a list of dictionaries with more than one key-value pair each, as long as the person's name is the first key, it will still work as of Python 3.7/3.6. See the note below this item:
Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was an implementation detail of CPython from 3.6.
>>> names = [{'Mark': 'Volvo', 'age': 30},
... {'John': 'BMW', 'age': 40},
... {'Eliza': 'Merci', 'age': 50},
... {'Calen': 'Audi', 'age': 60}]
>>> sorted(names, key=lambda d: order.index(list(d.keys())[0]))
[{'John': 'BMW', 'age': 40}, {'Mark': 'Volvo', 'age': 30}, {'Calen': 'Audi', 'age': 60}, {'Eliza': 'Merci', 'age': 50}]
>>>
First, if your dictionaries only have one entry, tuples seem to be a better choice for this data:
>>> names = [('Mark', 'Volvo'), ('John', 'BMW'), ('Eliza', 'Merci'), ('Calen', 'Audi')]
Now, given this order:
>>> order = ['John', 'Mark', 'Calen', 'Eliza']
you can create a dict that maps the names to the indices:
>>> order_map = { k: v for v, k in enumerate(order) }
>>> order_map
{'John': 0, 'Mark': 1, 'Calen': 2, 'Eliza': 3}
and use it in a key function for sort:
>>> names.sort(key=lambda v: order_map[v[0]])
>>> names
[('John', 'BMW'), ('Mark', 'Volvo'), ('Calen', 'Audi'), ('Eliza', 'Merci')]
names = [{'Mark':'Volvo'}, {'John':'BMW'}, {'Eliza':'Merci'}, {'Calen':'Audi'}]
ordered_keys = ['John','Mark','Calen','Eliza']
sorted_names = [name for key in ordered_keys for name in names if key in name]
It iterates over the ordered_keys in order and extracts any name in the list of dict that has that key.

Finding and printing max value from dictionaries within a list [duplicate]

I'm trying to get the index of the dictionary with the max 'size' in a list of dictionaries like the following:
ld = [{'prop': 'foo', 'size': 100}, {'prop': 'boo', 'size': 200}]
with the following code I can take the maximum size:
items = [x['size'] for x in ld]
print(max(items))
How can I take its index now? Is there an easy way?
Test:
I just figured I can do this:
items = [x['size'] for x in ld]
max_val = max(items)
print(items.index(max_val))
is this correct?
Tell max() how to calculate the maximum for a sequence of indices:
max(range(len(ld)), key=lambda index: ld[index]['size'])
This'll return the index for which the size key is the highest:
>>> ld = [{'prop': 'foo', 'size': 100}, {'prop': 'boo', 'size': 200}]
>>> max(range(len(ld)), key=lambda index: ld[index]['size'])
1
>>> ld[1]
{'size': 200, 'prop': 'boo'}
If you wanted that dictionary all along, then you could just use:
max(ld, key=lambda d: d['size'])
and to get both the index and the dictionary, you could use enumerate() here:
max(enumerate(ld), key=lambda item: item[1]['size'])
Some more demoing:
>>> max(ld, key=lambda d: d['size'])
{'size': 200, 'prop': 'boo'}
>>> max(enumerate(ld), key=lambda item: item[1]['size'])
(1, {'size': 200, 'prop': 'boo'})
The key function is passed each element in the input sequence in turn, and max() will pick the element where the return value of that key function is highest.
Using a separate list to extract all the size values then mapping that back to your original list is not very efficient (you now need to iterate over the list twice). list.index() cannot work as it has to match the whole dictionary, not just one value in it.
You can pass the enumerate(ld) to max function with a proper key :
>>> max(enumerate(ld),key=lambda arg:arg[1]['size'])[0]
1
If you just want the dictionary with max size value, as a Pythonic approach you could use operator.itemgetter function as the key:
In [10]: from operator import itemgetter
In [11]: ld = [{'prop': 'foo', 'size': 100}, {'prop': 'boo', 'size': 200}]
In [12]: fn = itemgetter('size')
In [13]: max(ld, key=fn)
Out[13]: {'prop': 'boo', 'size': 200}

How to iterate through a list of dictionaries

My code is
index = 0
for key in dataList[index]:
print(dataList[index][key])
Seems to work fine for printing the values of dictionary keys for index = 0. However, I can't figure out how to iterate through an unknown number of dictionaries in dataList.
You could just iterate over the indices of the range of the len of your list:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
for index in range(len(dataList)):
for key in dataList[index]:
print(dataList[index][key])
or you could use a while loop with an index counter:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
index = 0
while index < len(dataList):
for key in dataList[index]:
print(dataList[index][key])
index += 1
you could even just iterate over the elements in the list directly:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
for dic in dataList:
for key in dic:
print(dic[key])
It could be even without any lookups by just iterating over the values of the dictionaries:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
for dic in dataList:
for val in dic.values():
print(val)
Or wrap the iterations inside a list-comprehension or a generator and unpack them later:
dataList = [{'a': 1}, {'b': 3}, {'c': 5}]
print(*[val for dic in dataList for val in dic.values()], sep='\n')
the possibilities are endless. It's a matter of choice what you prefer.
You can easily do this:
for dict_item in dataList:
for key in dict_item:
print(dict_item[key])
It will iterate over the list, and for each dictionary in the list, it will iterate over the keys and print its values.
use=[{'id': 29207858, 'isbn': '1632168146', 'isbn13': '9781632168146', 'ratings_count': 0}]
for dic in use:
for val,cal in dic.items():
print(f'{val} is {cal}')
def extract_fullnames_as_string(list_of_dictionaries):
return list(map(lambda e : "{} {}".format(e['first'],e['last']),list_of_dictionaries))
names = [{'first': 'Zhibekchach', 'last': 'Myrzaeva'}, {'first': 'Gulbara', 'last': 'Zholdoshova'}]
print(extract_fullnames_as_string(names))
#Well...the shortest way (1 line only) in Python to extract data from the list of dictionaries is using lambda form and map together.
"""The approach that offers the most flexibility and just seems more dynamically appropriate to me is as follows:"""
Loop thru list in a Function called.....
def extract_fullnames_as_string(list_of_dictionaries):
result = ([val for dic in list_of_dictionaries for val in
dic.values()])
return ('My Dictionary List is ='result)
dataList = [{'first': 3, 'last': 4}, {'first': 5, 'last': 7},{'first':
15, 'last': 9},{'first': 51, 'last': 71},{'first': 53, 'last': 79}]
print(extract_fullnames_as_string(dataList))
"""This way, the Datalist can be any format of a Dictionary you throw at it, otherwise you can end up dealing with format issues, I found. Try the following and it will still works......."""
dataList1 = [{'a': 1}, {'b': 3}, {'c': 5}]
dataList2 = [{'first': 'Zhibekchach', 'last': 'Myrzaeva'}, {'first':
'Gulbara', 'last': 'Zholdoshova'}]
print(extract_fullnames_as_string(dataList1))
print(extract_fullnames_as_string(dataList2))
Another pythonic solution is using collections module.
Here is an example where I want to generate a dict containing only 'Name' and 'Last Name' values:
from collections import defaultdict
test_dict = [{'Name': 'Maria', 'Last Name': 'Bezerra', 'Age': 31},
{'Name': 'Ana', 'Last Name': 'Mota', 'Age': 31},
{'Name': 'Gabi', 'Last Name': 'Santana', 'Age': 31}]
collect = defaultdict(dict)
# at this moment, 'key' becomes every dict of your list of dict
for key in test_dict:
collect[key['Name']] = key['Last Name']
print(dict(collect))
Output should be:
{'Name': 'Maria', 'Last Name': 'Bezerra'}, {'Name': 'Ana', 'Last Name': 'Mota'}, {'Name': 'Gabi', 'Last Name': 'Santana'}
There are multiple ways to iterate through a list of dictionaries. However, if you are into Pythonic code, consider the following ways, but first, let's use data_list instead of dataList because in Python snake_case is preferred over camelCase.
Way #1: Iterating over a dictionary's keys
# let's assume that data_list is the following dictionary
data_list = [{'Alice': 10}, {'Bob': 7}, {'Charlie': 5}]
for element in data_list:
for key in element:
print(key, element[key])
Output
Alice 10
Bob 7
Charlie 5
Explanation:
for element in data_list: -> element will be a dictionary in data_list at each iteration, i.e., {'Alice': 10} in the first iteration,
{'Bob': 7} in the second iteration, and {'Charlie': 5}, in the third iteration.
for key in element: -> key will be a key of element at each iteration, so when element is {'Alice': 10}, the values for key will be 'Alice'. Keep in mind that element could contain more keys, but in this particular example it has just one.
print(key, element[key]) -> it prints key and the value of element for key key, i.e., it access the value of key in `element.
Way #2: Iterating over a dictionary's keys and values
# let's assume that data_list is the following dictionary
data_list = [{'Alice': 10}, {'Bob': 7}, {'Charlie': 5}]
for element in data_list:
for key, value in element.items():
print(key, value)
The output for this code snippet is the same as the previous one.
Explanation:
for element in data_list: -> it has the same explanation as the one in the code before.
for key, value in element.items(): -> at each iteration, element.items() will return a tuple that contains two elements. The former element is the key, and the latter is the value associated with that key, so when element is {'Alice': 10}, the value for key will be 'Alice', and the value for value will be 10. Keep in mind that this dictionary has only one key-value pair.
print(key, value) -> it prints key and value.
As stated before, there are multiple ways to iterate through a list of dictionaries, but to keep your code more Pythonic, avoid using indices or while loops.
had a similar issue, fixed mine by using a single for loop to iterate over the list, see code snippet
de = {"file_name":"jon","creation_date":"12/05/2022","location":"phc","device":"s3","day":"1","time":"44692.5708703703","year":"1900","amount":"3000","entity":"male"}
se = {"file_name":"bone","creation_date":"13/05/2022","location":"gar","device":"iphone","day":"2","time":"44693.5708703703","year":"2022","amount":"3000","entity":"female"}
re = {"file_name":"cel","creation_date":"12/05/2022","location":"ben car","device":"galaxy","day":"1","time":"44695.5708703703","year":"2022","amount":"3000","entity":"male"}
te = {"file_name":"teiei","creation_date":"13/05/2022","location":"alcon","device":"BB","day":"2","time":"44697.5708703703","year":"2022","amount":"3000","entity":"female"}
ye = {"file_name":"js","creation_date":"12/05/2022","location":"woji","device":"Nokia","day":"1","time":"44699.5708703703","year":"2022","amount":"3000","entity":"male"}
ue = {"file_name":"jsdjd","creation_date":"13/05/2022","location":"town","device":"M4","day":"5","time":"44700.5708703703","year":"2022","amount":"3000","entity":"female"}
d_list = [de,se,re,te,ye,ue]
for dic in d_list:
print (dic['file_name'],dic['creation_date'])

Categories