Finding the lowest values in an array of dict which also have matching attributes, returning the largest...
up vote
3
down vote
favorite
This is easy enough to do this with a few loops but I am sure there is a far more efficient way to achieve this and I am keen to learn.
Consider the following array of dict which represents data pulled from a nosql database.
x = [
{
"loc" : "alpha",
"tag" : 1,
"dist" : 5
},
{
"loc" : "bravo",
"tag" : 0,
"dist" : 2
},
{
"loc" : "charlie",
"tag" : 5,
"dist" : 50
},
{
"loc" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "echo",
"tag" : 2,
"dist" : 30
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
},
{
"loc" : "hotel",
"tag" : 0,
"dist" : 2
},
]
I would like to find all the items with the lowest 'dist' value, and should there be more than one dict with the same lowest value, I want the grouping on the attribute 'tag' that has the most dicts with the same lowest value.
for example, the desired returned data from the above would be:
r = [
{
"LocationName" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
}
]
Summary: dist:2 is the lowest value, [bravo, delta, foxtrot, gamma, hotel] all have a dist of 2, [bravo, hotel] have a tag of:0 and [delta, foxtrot, gamma] have a tag of:4 . An array of the dicts [delta, foxtrot, gamma] are returned as they have more with the same matching tag and the lowest dist.
I am using python 3.6.
Thank you for the help and interest!
python arrays python-3.x dictionary
add a comment |
up vote
3
down vote
favorite
This is easy enough to do this with a few loops but I am sure there is a far more efficient way to achieve this and I am keen to learn.
Consider the following array of dict which represents data pulled from a nosql database.
x = [
{
"loc" : "alpha",
"tag" : 1,
"dist" : 5
},
{
"loc" : "bravo",
"tag" : 0,
"dist" : 2
},
{
"loc" : "charlie",
"tag" : 5,
"dist" : 50
},
{
"loc" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "echo",
"tag" : 2,
"dist" : 30
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
},
{
"loc" : "hotel",
"tag" : 0,
"dist" : 2
},
]
I would like to find all the items with the lowest 'dist' value, and should there be more than one dict with the same lowest value, I want the grouping on the attribute 'tag' that has the most dicts with the same lowest value.
for example, the desired returned data from the above would be:
r = [
{
"LocationName" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
}
]
Summary: dist:2 is the lowest value, [bravo, delta, foxtrot, gamma, hotel] all have a dist of 2, [bravo, hotel] have a tag of:0 and [delta, foxtrot, gamma] have a tag of:4 . An array of the dicts [delta, foxtrot, gamma] are returned as they have more with the same matching tag and the lowest dist.
I am using python 3.6.
Thank you for the help and interest!
python arrays python-3.x dictionary
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
This is easy enough to do this with a few loops but I am sure there is a far more efficient way to achieve this and I am keen to learn.
Consider the following array of dict which represents data pulled from a nosql database.
x = [
{
"loc" : "alpha",
"tag" : 1,
"dist" : 5
},
{
"loc" : "bravo",
"tag" : 0,
"dist" : 2
},
{
"loc" : "charlie",
"tag" : 5,
"dist" : 50
},
{
"loc" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "echo",
"tag" : 2,
"dist" : 30
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
},
{
"loc" : "hotel",
"tag" : 0,
"dist" : 2
},
]
I would like to find all the items with the lowest 'dist' value, and should there be more than one dict with the same lowest value, I want the grouping on the attribute 'tag' that has the most dicts with the same lowest value.
for example, the desired returned data from the above would be:
r = [
{
"LocationName" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
}
]
Summary: dist:2 is the lowest value, [bravo, delta, foxtrot, gamma, hotel] all have a dist of 2, [bravo, hotel] have a tag of:0 and [delta, foxtrot, gamma] have a tag of:4 . An array of the dicts [delta, foxtrot, gamma] are returned as they have more with the same matching tag and the lowest dist.
I am using python 3.6.
Thank you for the help and interest!
python arrays python-3.x dictionary
This is easy enough to do this with a few loops but I am sure there is a far more efficient way to achieve this and I am keen to learn.
Consider the following array of dict which represents data pulled from a nosql database.
x = [
{
"loc" : "alpha",
"tag" : 1,
"dist" : 5
},
{
"loc" : "bravo",
"tag" : 0,
"dist" : 2
},
{
"loc" : "charlie",
"tag" : 5,
"dist" : 50
},
{
"loc" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "echo",
"tag" : 2,
"dist" : 30
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
},
{
"loc" : "hotel",
"tag" : 0,
"dist" : 2
},
]
I would like to find all the items with the lowest 'dist' value, and should there be more than one dict with the same lowest value, I want the grouping on the attribute 'tag' that has the most dicts with the same lowest value.
for example, the desired returned data from the above would be:
r = [
{
"LocationName" : "delta",
"tag" : 4,
"dist" : 2
},
{
"loc" : "foxtrot",
"tag" : 4,
"dist" : 2
},
{
"loc" : "gamma",
"tag" : 4,
"dist" : 2
}
]
Summary: dist:2 is the lowest value, [bravo, delta, foxtrot, gamma, hotel] all have a dist of 2, [bravo, hotel] have a tag of:0 and [delta, foxtrot, gamma] have a tag of:4 . An array of the dicts [delta, foxtrot, gamma] are returned as they have more with the same matching tag and the lowest dist.
I am using python 3.6.
Thank you for the help and interest!
python arrays python-3.x dictionary
python arrays python-3.x dictionary
edited Nov 11 at 10:15
ChaosPredictor
1,87511523
1,87511523
asked Nov 11 at 0:50
Xavier Hutchinson
1,2311019
1,2311019
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
2
down vote
accepted
You can specify a key
(that is, a lambda function) for max()
and min()
that can help with this. For your first test,
lowest_single_dist = min(x, key=lambda i: i["dist"])
returns the element in x
with the lowest value for "dist"
. If you then want all of the elements with that tag value, you can use a list comprehension:
lowest_dists = [i for i in x if i["dist"] == lowest_single_dist["dist"]]
To get the largest grouping, I would first create a set of the possible values for "tag"
in that subset, and then check how many of each there are in lowest_dists
, then take whichever one has the highest count:
tags = [i["tag"] for i in lowest_dists] # get a list of just the tags
ct = {t: tags.count(t) for t in set(tags)} # make a dict of tag:count for each unique tag
max_tag = max(ct, key=lambda x: ct[x]) # find the largest count and get the largest tag
r = [i for i in lowest_dists if i["tag"] == max_tag] # use another list comprehension to get all the max tags
If you wanted to shorten it all into a two-liner, you could be less pythonic and do this:
m = min(x, key=lambda i: (i["dist"], -1 * max([j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])))
r = [i for i in x if i["tag"] == m["tag"] and i["dist"] == m["dist"]]
This takes advantage of the fact that you can return a tuple as the key for sorting, and the second value of the tuple will only be checked if the first is equal. I'll expand that first line a bit and explain what each part is doing:
m = min(x, key=lambda i: (
i["dist"], -1 * max(
[j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])
))
- The innermost list comprehension generates a list of the tags for all elements in
x
with the same value for"dist"
asi
- Then, take the count of tags that are the same as
i
- Multiply by -1 to make it negative so that
min()
behaves correctly - make a tuple of
i["dist"]
and the value we just calculated (the frequency ofi["tag"]
inx
), and return that for each element - assign to
m
the element of the list that has the lowest value for"dist"
and the most frequent value for"tag"
- assign to
r
the sublist of elements inx
with the same value for"dist"
and"tag"
So basically the same process as above, but shorter, less efficient, and a bit more complicated.
Brilliant, thank you so much - I learned a lot from this solution
– Xavier Hutchinson
Nov 11 at 5:37
add a comment |
up vote
0
down vote
sort the list of dictionaries by the value they have at 'dist' and take the lowest
x.sort(key= lambda x:x['dist'])
lowest = x[0]['dist']
create a list of dictionaries with the value for 'dist' equal to the lowest
x2 = [i for i in x if i['dist']==lowest]
This should be your answer. If there is more than one item in the list, repeat the above procedure.
if len(x2)>1:
x3 = [i['tag'] for i in x2]
mode = max(set(x3), key=x3.count)
r = [i for i in x if i['tag']==mode]
2
While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find how to write a good answer very helpful. Please edit your answer.
– hellow
Nov 11 at 7:19
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
You can specify a key
(that is, a lambda function) for max()
and min()
that can help with this. For your first test,
lowest_single_dist = min(x, key=lambda i: i["dist"])
returns the element in x
with the lowest value for "dist"
. If you then want all of the elements with that tag value, you can use a list comprehension:
lowest_dists = [i for i in x if i["dist"] == lowest_single_dist["dist"]]
To get the largest grouping, I would first create a set of the possible values for "tag"
in that subset, and then check how many of each there are in lowest_dists
, then take whichever one has the highest count:
tags = [i["tag"] for i in lowest_dists] # get a list of just the tags
ct = {t: tags.count(t) for t in set(tags)} # make a dict of tag:count for each unique tag
max_tag = max(ct, key=lambda x: ct[x]) # find the largest count and get the largest tag
r = [i for i in lowest_dists if i["tag"] == max_tag] # use another list comprehension to get all the max tags
If you wanted to shorten it all into a two-liner, you could be less pythonic and do this:
m = min(x, key=lambda i: (i["dist"], -1 * max([j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])))
r = [i for i in x if i["tag"] == m["tag"] and i["dist"] == m["dist"]]
This takes advantage of the fact that you can return a tuple as the key for sorting, and the second value of the tuple will only be checked if the first is equal. I'll expand that first line a bit and explain what each part is doing:
m = min(x, key=lambda i: (
i["dist"], -1 * max(
[j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])
))
- The innermost list comprehension generates a list of the tags for all elements in
x
with the same value for"dist"
asi
- Then, take the count of tags that are the same as
i
- Multiply by -1 to make it negative so that
min()
behaves correctly - make a tuple of
i["dist"]
and the value we just calculated (the frequency ofi["tag"]
inx
), and return that for each element - assign to
m
the element of the list that has the lowest value for"dist"
and the most frequent value for"tag"
- assign to
r
the sublist of elements inx
with the same value for"dist"
and"tag"
So basically the same process as above, but shorter, less efficient, and a bit more complicated.
Brilliant, thank you so much - I learned a lot from this solution
– Xavier Hutchinson
Nov 11 at 5:37
add a comment |
up vote
2
down vote
accepted
You can specify a key
(that is, a lambda function) for max()
and min()
that can help with this. For your first test,
lowest_single_dist = min(x, key=lambda i: i["dist"])
returns the element in x
with the lowest value for "dist"
. If you then want all of the elements with that tag value, you can use a list comprehension:
lowest_dists = [i for i in x if i["dist"] == lowest_single_dist["dist"]]
To get the largest grouping, I would first create a set of the possible values for "tag"
in that subset, and then check how many of each there are in lowest_dists
, then take whichever one has the highest count:
tags = [i["tag"] for i in lowest_dists] # get a list of just the tags
ct = {t: tags.count(t) for t in set(tags)} # make a dict of tag:count for each unique tag
max_tag = max(ct, key=lambda x: ct[x]) # find the largest count and get the largest tag
r = [i for i in lowest_dists if i["tag"] == max_tag] # use another list comprehension to get all the max tags
If you wanted to shorten it all into a two-liner, you could be less pythonic and do this:
m = min(x, key=lambda i: (i["dist"], -1 * max([j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])))
r = [i for i in x if i["tag"] == m["tag"] and i["dist"] == m["dist"]]
This takes advantage of the fact that you can return a tuple as the key for sorting, and the second value of the tuple will only be checked if the first is equal. I'll expand that first line a bit and explain what each part is doing:
m = min(x, key=lambda i: (
i["dist"], -1 * max(
[j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])
))
- The innermost list comprehension generates a list of the tags for all elements in
x
with the same value for"dist"
asi
- Then, take the count of tags that are the same as
i
- Multiply by -1 to make it negative so that
min()
behaves correctly - make a tuple of
i["dist"]
and the value we just calculated (the frequency ofi["tag"]
inx
), and return that for each element - assign to
m
the element of the list that has the lowest value for"dist"
and the most frequent value for"tag"
- assign to
r
the sublist of elements inx
with the same value for"dist"
and"tag"
So basically the same process as above, but shorter, less efficient, and a bit more complicated.
Brilliant, thank you so much - I learned a lot from this solution
– Xavier Hutchinson
Nov 11 at 5:37
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
You can specify a key
(that is, a lambda function) for max()
and min()
that can help with this. For your first test,
lowest_single_dist = min(x, key=lambda i: i["dist"])
returns the element in x
with the lowest value for "dist"
. If you then want all of the elements with that tag value, you can use a list comprehension:
lowest_dists = [i for i in x if i["dist"] == lowest_single_dist["dist"]]
To get the largest grouping, I would first create a set of the possible values for "tag"
in that subset, and then check how many of each there are in lowest_dists
, then take whichever one has the highest count:
tags = [i["tag"] for i in lowest_dists] # get a list of just the tags
ct = {t: tags.count(t) for t in set(tags)} # make a dict of tag:count for each unique tag
max_tag = max(ct, key=lambda x: ct[x]) # find the largest count and get the largest tag
r = [i for i in lowest_dists if i["tag"] == max_tag] # use another list comprehension to get all the max tags
If you wanted to shorten it all into a two-liner, you could be less pythonic and do this:
m = min(x, key=lambda i: (i["dist"], -1 * max([j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])))
r = [i for i in x if i["tag"] == m["tag"] and i["dist"] == m["dist"]]
This takes advantage of the fact that you can return a tuple as the key for sorting, and the second value of the tuple will only be checked if the first is equal. I'll expand that first line a bit and explain what each part is doing:
m = min(x, key=lambda i: (
i["dist"], -1 * max(
[j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])
))
- The innermost list comprehension generates a list of the tags for all elements in
x
with the same value for"dist"
asi
- Then, take the count of tags that are the same as
i
- Multiply by -1 to make it negative so that
min()
behaves correctly - make a tuple of
i["dist"]
and the value we just calculated (the frequency ofi["tag"]
inx
), and return that for each element - assign to
m
the element of the list that has the lowest value for"dist"
and the most frequent value for"tag"
- assign to
r
the sublist of elements inx
with the same value for"dist"
and"tag"
So basically the same process as above, but shorter, less efficient, and a bit more complicated.
You can specify a key
(that is, a lambda function) for max()
and min()
that can help with this. For your first test,
lowest_single_dist = min(x, key=lambda i: i["dist"])
returns the element in x
with the lowest value for "dist"
. If you then want all of the elements with that tag value, you can use a list comprehension:
lowest_dists = [i for i in x if i["dist"] == lowest_single_dist["dist"]]
To get the largest grouping, I would first create a set of the possible values for "tag"
in that subset, and then check how many of each there are in lowest_dists
, then take whichever one has the highest count:
tags = [i["tag"] for i in lowest_dists] # get a list of just the tags
ct = {t: tags.count(t) for t in set(tags)} # make a dict of tag:count for each unique tag
max_tag = max(ct, key=lambda x: ct[x]) # find the largest count and get the largest tag
r = [i for i in lowest_dists if i["tag"] == max_tag] # use another list comprehension to get all the max tags
If you wanted to shorten it all into a two-liner, you could be less pythonic and do this:
m = min(x, key=lambda i: (i["dist"], -1 * max([j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])))
r = [i for i in x if i["tag"] == m["tag"] and i["dist"] == m["dist"]]
This takes advantage of the fact that you can return a tuple as the key for sorting, and the second value of the tuple will only be checked if the first is equal. I'll expand that first line a bit and explain what each part is doing:
m = min(x, key=lambda i: (
i["dist"], -1 * max(
[j["tag"] for j in x if j["dist"] == i["dist"]].count(i["tag"])
))
- The innermost list comprehension generates a list of the tags for all elements in
x
with the same value for"dist"
asi
- Then, take the count of tags that are the same as
i
- Multiply by -1 to make it negative so that
min()
behaves correctly - make a tuple of
i["dist"]
and the value we just calculated (the frequency ofi["tag"]
inx
), and return that for each element - assign to
m
the element of the list that has the lowest value for"dist"
and the most frequent value for"tag"
- assign to
r
the sublist of elements inx
with the same value for"dist"
and"tag"
So basically the same process as above, but shorter, less efficient, and a bit more complicated.
edited Nov 11 at 7:35
answered Nov 11 at 1:22
Green Cloak Guy
2,188720
2,188720
Brilliant, thank you so much - I learned a lot from this solution
– Xavier Hutchinson
Nov 11 at 5:37
add a comment |
Brilliant, thank you so much - I learned a lot from this solution
– Xavier Hutchinson
Nov 11 at 5:37
Brilliant, thank you so much - I learned a lot from this solution
– Xavier Hutchinson
Nov 11 at 5:37
Brilliant, thank you so much - I learned a lot from this solution
– Xavier Hutchinson
Nov 11 at 5:37
add a comment |
up vote
0
down vote
sort the list of dictionaries by the value they have at 'dist' and take the lowest
x.sort(key= lambda x:x['dist'])
lowest = x[0]['dist']
create a list of dictionaries with the value for 'dist' equal to the lowest
x2 = [i for i in x if i['dist']==lowest]
This should be your answer. If there is more than one item in the list, repeat the above procedure.
if len(x2)>1:
x3 = [i['tag'] for i in x2]
mode = max(set(x3), key=x3.count)
r = [i for i in x if i['tag']==mode]
2
While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find how to write a good answer very helpful. Please edit your answer.
– hellow
Nov 11 at 7:19
add a comment |
up vote
0
down vote
sort the list of dictionaries by the value they have at 'dist' and take the lowest
x.sort(key= lambda x:x['dist'])
lowest = x[0]['dist']
create a list of dictionaries with the value for 'dist' equal to the lowest
x2 = [i for i in x if i['dist']==lowest]
This should be your answer. If there is more than one item in the list, repeat the above procedure.
if len(x2)>1:
x3 = [i['tag'] for i in x2]
mode = max(set(x3), key=x3.count)
r = [i for i in x if i['tag']==mode]
2
While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find how to write a good answer very helpful. Please edit your answer.
– hellow
Nov 11 at 7:19
add a comment |
up vote
0
down vote
up vote
0
down vote
sort the list of dictionaries by the value they have at 'dist' and take the lowest
x.sort(key= lambda x:x['dist'])
lowest = x[0]['dist']
create a list of dictionaries with the value for 'dist' equal to the lowest
x2 = [i for i in x if i['dist']==lowest]
This should be your answer. If there is more than one item in the list, repeat the above procedure.
if len(x2)>1:
x3 = [i['tag'] for i in x2]
mode = max(set(x3), key=x3.count)
r = [i for i in x if i['tag']==mode]
sort the list of dictionaries by the value they have at 'dist' and take the lowest
x.sort(key= lambda x:x['dist'])
lowest = x[0]['dist']
create a list of dictionaries with the value for 'dist' equal to the lowest
x2 = [i for i in x if i['dist']==lowest]
This should be your answer. If there is more than one item in the list, repeat the above procedure.
if len(x2)>1:
x3 = [i['tag'] for i in x2]
mode = max(set(x3), key=x3.count)
r = [i for i in x if i['tag']==mode]
edited Nov 11 at 15:19
answered Nov 11 at 1:17
qwerty asdf
92
92
2
While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find how to write a good answer very helpful. Please edit your answer.
– hellow
Nov 11 at 7:19
add a comment |
2
While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find how to write a good answer very helpful. Please edit your answer.
– hellow
Nov 11 at 7:19
2
2
While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find how to write a good answer very helpful. Please edit your answer.
– hellow
Nov 11 at 7:19
While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find how to write a good answer very helpful. Please edit your answer.
– hellow
Nov 11 at 7:19
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244865%2ffinding-the-lowest-values-in-an-array-of-dict-which-also-have-matching-attribute%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown