Reputation: 49
I want to find and return the minimal value of an id in a string, for example:
find_min_id([{"nonid": "-222", "id": 0}, {"id": -101}])
-101
find_min_id([{’id’: 63, 'id': 42}])
42
So far I have this:
def find_min_id(list):
return min(list)
but that gives:
{'id': -101}
and I only want the value of the lowest id.
Upvotes: 5
Views: 2515
Reputation: 35891
Another approach, but works where there is no id
in the dictionary, and when there is no dictionary with an id
at all:
def find_min_id(lst):
ids = [d['id'] for d in lst if 'id' in d]
return min(ids) if ids else None
Without exceptions, and without running min
for artificially extended list (i.e. the answer which puts maximum floats where an entry isn't an id-entry).
Upvotes: 2
Reputation: 229331
Use the key
parameter of min
:
def find_min_id(l):
return min(l, key=lambda d: d.get("id", float('inf')))["id"]
This actually finds the min id, and does it without creating a new list.
The only thing is, the elements in your list might not had an 'id'
key. For that reason I had to use .get("id", float('inf'))
. Thus the function will return inf
if there is no id key, which might not be desirable. What min()
does when given an empty list is it throws an exception, so we'd probably like to do the same if none of the dicts we pass it have an 'id'
key. In that case the min of a generator appoach might indeed be better:
def find_min_id(l):
return min(d["id"] for d in l if "id" in d)
The other approach would be to check for inf
as the result of min
, but this is more cumbersome:
import math
def find_min_id(l):
res = min(l, key=lambda d: d.get("id", float('inf')))["id"]
if math.isinf(res):
raise ValueError("No dict has an 'id' key")
return res
Upvotes: 7
Reputation: 82470
>>> ids = [{"nonid": "-222", "id": 0}, {"id": -101}]
>>> min([val for obj in ids for key, val in obj.items() if key == 'id'])
-101
>>> ids = [{'id': 63}, { 'id': 42}]
>>> min([val for obj in ids for key, val in obj.items() if key == 'id'])
42
Try the above.
You can make this into a function definition:
def find_lowest(ids):
return min([val for obj in ids for key, val in obj.items() if key == 'id'])
Working example.
Let me explain what I'm doing. Firstly, the min
function takes in an iterable object as an argument. So, let me demonstrate:
>>> min([1,2,3,4,6,1,0])
0
So, what this means is this, we are essentially taking the minimum value of the list that we get from this, [val for obj in ids for key, val in obj.items() if key == 'id']
.
Now, you might be wondering, well whats happening in there? It might be a little intimidating at first, but thats a list comprehension. Whats that you say? Well, in simple terms its a concise we in which we make a list:
Let me start with be first part, and no its not the beginning of the statement:
for obj in ids
What we are doing here, is iterating over all the dictionary objects in in side of ids
. Now, we use that object here:
key, val in obj.items() if key == 'id'
Since object, is a dict
, we use the items
function to get a generator that gives a tuple of key, value pairs. In an object like this: {'id': 100}
, the id
would be they key and 100
would be the value. So, we are going over all the items in the dictionary object, and if the key
happens to be id
, then we append it to the list:
[val
Thats what the first part does. The first part of the list comprehension appends something to the final list, and that is val
.
If for some reason, the list does not containt anything with id
as a key, then it will throw a ValueError
as min
does not accept an empty list, so to remedy this, we can check:
def find_lowest(ids):
_ret = [val for obj in ids for key, val in obj.items() if key == 'id']
if _ret:
return min(_ret)
else:
return None
Upvotes: 1
Reputation: 28252
You are trying to find the 'lowest' dictionaries. What we want is, to find the lowest 'id'
value in the list.
def find_min_id(lst):
return min([d[key] for key in d for d in lst if key=="id"])
Also, avoid using list
as a variable name, it overrides the built-in function list()
.
A little demo:
>>> def find_min_id(lst):
return min([d[key] for key in d for d in lst if key=="id"])
>>> find_min_id(lst)
-101
Hope this helps!
Upvotes: 1
Reputation: 48317
Following code return None
if no id
key is in list.
>>> data = [{"nonid": "-222", "id": 0}, {"id": -101}, {"nonid":-200}]
>>> min(filter(lambda x: x is not None, map(lambda x: x.get('id', None),
... data)) or [None])
-101
Here filter(lambda x: x is not None, ...)
filters out dictionaries without id,
map(lambda x: x.get('id', None), data)
gets all id
's from data, and or [None]
part treats case when no id
key will be found in data.
Upvotes: 1
Reputation: 9680
list
is a built-in type in Python. don't use it as an identifier
def find_min_id(my_list)
id_list = []
for record in my_list:
if 'id' in record:
id_list.append(record['id'])
return min(id_list)
Upvotes: 0