Python: Sorting an array based on a subvalue [duplicate] - python

This question already has answers here:
How do I sort a dictionary by value?
(34 answers)
Closed 8 years ago.
I have the following data structure:
[
{ some: thing9,
key: 9,
},
{ some: thing3,
key: 3,
},
{ some: thing2,
key: 2,
},
{ some: thing1,
key: 1,
}
]
How can I sort this array based on the key value of the dictionary so I get:
[
{ some: thing1,
key: 1,
},
{ some: thing2,
key: 2,
},
{ some: thing3,
key: 3,
},
{ some: thing9,
key: 9,
}
]
Thanks

sorted(data, key=operator.itemgetter('key'))
The Sorting HOWTO explains this in more detail. But the basic idea is that all sort-related functions take a key argument, a callable that's applied to each value before comparing the values.
So, we want key to take one of the elements of your list, and return the thing you want to sort by. The elements are dicts, and you want to sort by their key item. The itemgetter function does exactly what you want. (If that function weren't available, you could use, e.g., lambda item: item['key'] instead.)

If you prefer to use lambda expressions, this is also an suitable way of solving your problem:
sorted(data, key=lambda x: x['key'])
So:
from pprint import pprint
data = [
{ 'some': 'thing9',
'key': 9,
},
{ 'some': 'thing3',
'key': 3,
},
{ 'some': 'thing2',
'key': 2,
},
{ 'some': 'thing1',
'key': 1,
}
]
pprint(sorted(data, key=lambda x:x['key']))
outputs
[{'key': 1, 'some': 'thing1'},
{'key': 2, 'some': 'thing2'},
{'key': 3, 'some': 'thing3'},
{'key': 9, 'some': 'thing9'}]

Related

Nested dictionary comprehension (2 level)

I have a list of dictionary objects
data = [
{
'id': 1,
'parent_id': 101 ,
'name': 'A'
},
{
'id': 2,
'parent_id': 101,
'name': 'B'
},
{
'id': 3,
'parent_id': 102,
'name': 'C'
},
{
'id': 4,
'parent_id': 102,
'name': 'D'
}
]
I want to convert this to a nested dictionary.
Structure:
{
parent_id_value: {
name_value: id_value
}
}
Result of the sample list of dictionary object should be like this
{
101: {
'A': 1,
'B': 2
},
102: {
'C': 3,
'D': 4
}
}
I know we can run a for loop and use setdefault to set/get paren_id value and then add the name and id as key, value
new_dic = {}
for i in data:
new_dic.setdefault(i['parent_id'], {})[i['name']] = i['id']
print(new_dic)
But I am looking for a more pythonic way, meaning is it possible through dictionary comprehension?
So you want to play the comprehension game and you want to see a pro player at it.
Forget about itertools, forget about multiple statements. Here is the ultimate comprehension that will make any programmer working on your code throw the keyboard away and leave the room cursing you.
data = {parent_id: {d["name"]: d["id"] for d in [i for i in data if i["parent_id"] == parent_id]} for parent_id in set((j["parent_id"] for j in data))}
But for real though, don't do this in your code if it's going to be shared with someone.
First, sort the list using operator.itemgetter to supply the key:
data.sort(key=itemgetter('parent_id'))
Then use itertools.groupby to group the intended sections in a nested dict-comprehension:
data = {
key: {item['name']: item['id'] for item in group}
for key, group in groupby(data, itemgetter('parent_id'))
}
I don't recommend writing a one-liner, but you can do it with sorted:
data = {
key: {item['name']: item['id'] for item in group}
for key, group in groupby(sorted(data, key=itemgetter('parent_id')), itemgetter('parent_id'))
}

How do i get the biggest value from a dictionary?

i still learning python3. please help my problem :)
i have a dictionary
"527740905101197317": {
"lvl": 7,
"exp": 6,
"gems": 333,
"items": {},
"bank": 0
},
"600576767777832972": {
"lvl": 6,
"exp": 14,
"gems": 100,
"items": {},
"bank": 0
},
"580843977352413185": {
"lvl": 1,
"exp": 700,
"gems": 6765,
"items": {},
"bank": 0
},
"720726494640341161": {
"lvl": 3,
"exp": 2,
"gems": 1234,
"items": {},
"bank": 0
},
"657959364933451796": {
"lvl": 1,
"exp": 480,
"gems": 42,
"items": {},
"bank": 0
},
"724932280405065830": {
"lvl": 1,
"exp": 1,
"gems": 1256,
"items": {}
},
how do i get the biggest "gems" with python3?
i've tried some of tutorial, but none of it work.
Iterate over all the dictionaries using the .values() method, select the 'gems' value, and take the maximum.
max(d['gems'] for d in my_data.values())
I'd reccomend using a built-in max function, and specifying a key argument:
max_gems_key = max(dictionary, key=lambda a: dictionary[a]['gems'])
max_gems_val = dictionary[max_gems_key]
Let me simplify and break down everything:
def keyFunction(a):
return dictionary[a]['gems']
max_gems_key = max(dictionary, key=keyFunction)
max_gems_val = dictionary[max_gems_key]
What is happening: I first create a function that finds gems when received the dictionary key - the gems value is what max would use to indentify what's larger, since you can't tell what's larger without it (e.g. is {'a':1,'b':2} > {'a':2,'b':1}?). Then, I call the max function, and it iterates through all the keys, finding the biggest - it, again, uses keyFunc to determine how big a key is, and assignes the biggest key to max_gems_key. A little further information about max usage here.
Hope that's helpful!
As this is a nested dictionary if you want it using pandas you can try this way too.
import pandas as pd
df = pd.DataFrame(data_dict).T
df['gems'].max()
The simplest way if you are a beginner is just to loop over the key,value pairs and keep track of the key for the largest one. Here is a reference to the docs about looping over dictionary items.
You have a nested dictionary, so you are going to loop over the outer dictionary and examine the entries in the inner dictionary to find the largest.
Something like this:
def find_max(my_dict):
key_for_max = None
max_gem = -1
# loop over outer dictionary
for key, value in my_dict.items():
# look into inner dictionary items to find maximum value for the 'gems' key
if value['gems'] > max_gem:
max_gem = value['gems']
key_for_max = key
return key_for_max, max_gem
I am assuming that you want the key for the entry that has the max 'gems' value, not just the value itself.
Other alternatives are to sort it using the 'gems' value as a sorting key, but this is likely the simplest for you to follow as a newer programmer.

Finding key in a list of dictionaries and sorting the list [duplicate]

This question already has answers here:
How do I sort a list of dictionaries by a value of the dictionary?
(20 answers)
Closed 3 years ago.
Having a JSON-like structure:
{
"shopping_list": [
{
"level": 0,
"position": 0,
"item_name": "Gold Badge"
},
{
"level": 1,
"position": 10,
"item_name": "Silver Badge"
},
{
"level": 2,
"position": 20,
"item_name": "Bronze Badge"
}
]
}
I'm trying to sort the list by key.
However, when trying to get them by:
k = [c.keys()[0] for c in complete_list["shopping_list"]]
I get TypeError: 'dict_keys' object does not support indexing.
How to get keys?
How to sort the list by specified key?
Here it is (admitting the key you mention is 'level'):
k = sorted([c for c in complete_list["shopping_list"]], key=lambda x: x['level'])
print(k)
# >> [{'level': 0, 'position': 0, 'item_name': 'Gold Badge'}, {'level': 1, 'position': 10, 'item_name': 'Silver Badge'}, ...
Try this to get the keys in a list of lists :
d = {
"shopping_list": [
...
}
k = [list(c.keys()) for c in d["shopping_list"]]
print(k)
Output :
[['item_name', 'level', 'position'], ['item_name', 'level', 'position'], ['item_name', 'level', 'position']]
However even if you wanted to sort this list of lists based on some specific key value say value for "level" key or "position" key, the list of lists would remain same.

How to set specific attributes of a dictionary to []

Let us imagine the following dictionary
dictionary = {
"key1": {
"value": [1, 3, 5],
},
"key2": {
"value": [1, 2, -1],
},
}
Is it possible to set all the "values" to [] without iterating over the dictionary keys? I want something like dictionary[]["value"]=[] such that all "value" attributes are set to []. But that doesn't work.
Because you need to avoid iteration, here is a little hacky way of solving the case.
Convert dictionary to string, replace and then back to dictionary:
import re, ast
dictionary = {
"key1": {
"value": [1, 3, 5],
},
"key2": {
"value": [1, 2, -1],
},
}
print(ast.literal_eval(re.sub(r'\[.*?\]', '[]', str(dictionary))))
# {'key1': {'value': []}, 'key2': {'value': []}}
I'm going to take a different tack here. Your question is a little misinformed. The implication is that it's "better" to avoid iterating dictionary keys. As mentioned, you can iterate over dictionary values. But, since internally Python stores dictionaries via two arrays, iteration is unavoidable.
Returning to your core question:
I want something like dictionary[]["value"]=[] such that all "value"
attributes are set to [].
Just use collections.defaultdict:
from collections import defaultdict
d = {k: defaultdict(list) for k in dictionary}
print(d['key1']['value']) # []
print(d['key2']['value']) # []
For the dictionary structure you have defined, this will certainly be more efficient than string conversion via repr + regex substitution.
If you insist on explicitly setting keys, you can avoid defaultdict at the cost of an inner dictionary comprehension:
d = {k: {i: [] for i in v} for k, v in dictionary.items()}
{'key1': {'value': []}, 'key2': {'value': []}}

Merging 2 dictionaries in python

I have two dictionary:
a=
{
"2001935072": {
"WR": "48.9",
"nickname": "rogs30541",
"team": 2
},
....
}
and
b=
{
"2001935072": {
"wtr": 816
},
....
}
i've tried to merge them with both a.update(b) and a={**a, **b} but both gives this output when i print(a):
{
"2001935072": {
"wtr": 816
},
....
}
which is basicly a=b, how to merge A and B so the output is
{
"2001935072": {
"WR": "48.9",
"nickname": "rogs30541",
"team": 2
"wtr": 816
},
....
}
I would compute the union of the keys, then rebuild the dictionary merging the inner dictionaries together with an helper method (because dict merging is possible in 3.6+ inline but not before) (How to merge two dictionaries in a single expression?)
a={
"2001935072": {
"WR": "48.9",
"nickname": "rogs30541",
"team": 2
}
}
b= {
"2001935072": {
"wtr": 816
},
}
def merge_two_dicts(x, y):
"""Given two dicts, merge them into a new dict as a shallow copy."""
z = x.copy()
z.update(y)
return z
result = {k:merge_two_dicts(a.get(k,{}),b.get(k,{})) for k in set(a)|set(b)}
print(result)
result:
{'2001935072': {'WR': '48.9', 'nickname': 'rogs30541', 'team': 2, 'wtr': 816}}
notes:
a.get(k,{}) allows to get the value for k with a default of so merge still works, only retaining values from b dict.
merge_two_dicts is just an helper function. Not to be used with a and b dicts directly or it will give the wrong result, since last merged one "wins" and overwrites the other dict values
With Python 3.6+: you can do that without any helper function:
result = {k:{**a.get(k,{}),**b.get(k,{})} for k in set(a)|set(b)}
Try this:-
for i,j in a.items():
for x,y in b.items():
if i==x:
j.update(y)
print(a) #your updateed output
You can try list + dict comprehension to achieve your results:
>>> a = {"2001935072":{"WR":"48.9","nickname":"rogs30541","team":2}}
>>> b = {"2001935072":{"wtr":816}}
>>> l = dict([(k,a.get(k),b.get(k)) for k in set(list(a.keys()) + list(b.keys()))])
This will output:
>>> [('2001935072', {'WR': '48.9', 'nickname': 'rogs30541', 'team': 2}, {'wtr': 816})]
Finally to achieve your desired output
>>> dict((k,{**va,**vb}) for k,va,vb in l)
>>> {'2001935072': {'WR': '48.9', 'nickname': 'rogs30541', 'team': 2, 'wtr': 816}}

Categories

Resources