I am new to python and I am trying to construct data structure from existing data.
I have following:
[
{'UserName': 'aaa', 'AccessKeyId': 'AKIAYWQTISJD6X27YVK', 'Status': 'Active', 'CreateDate': datetime.datetime(2022, 9, 8, 15, 56, 39, tzinfo=tzutc())},
{'UserName': 'eee', 'AccessKeyId': 'AKIAYWQTISJD6QXMAKY', 'Status': 'Active', 'CreateDate': datetime.datetime(2023, 1, 24, 12, 30, 59, tzinfo=tzutc())},
{'UserName': 'eee', 'AccessKeyId': 'AKIAYWQTISJDUARK6FV', 'Status': 'Active', 'CreateDate': datetime.datetime(2023, 1, 24, 16, 58, 38, tzinfo=tzutc())}
]
I need to get this:
{
"aaa": [
{'AccessKeyId': 'AKIAYWQTISJD6X27YVK', 'Status': 'Active', 'CreateDate': datetime.datetime(2022, 9, 8, 15, 56, 39, tzinfo=tzutc())}],
"eee": [
{'AccessKeyId': 'AKIAYWQTISJD6QXMAKY', 'Status': 'Active', 'CreateDate': datetime.datetime(2023, 1, 24, 12, 30, 59, tzinfo=tzutc())},
{'AccessKeyId': 'AKIAYWQTISJDUARK6FV', 'Status': 'Active', 'CreateDate': datetime.datetime(2023, 1, 24, 16, 58, 38, tzinfo=tzutc())}
]
}
I tried following:
list_per_user = {i['UserName']: copy.deepcopy(i) for i in key_list}
for obj in list_per_user:
del list_per_user[obj]['UserName']
but I am missing array here. So in case of two keys per user I will have only last one with this. I don't know how to get the list I need per user.
Thanks!
Create an external dict that maps username -> list of entries.
data = [
{'UserName': 'aaa', 'AccessKeyId': 'AKIAYWQTISJD6X27YVK', 'Status': 'Active', 'CreateDate': datetime.datetime(2022, 9, 8, 15, 56, 39, tzinfo=tzutc())},
{'UserName': 'eee', 'AccessKeyId': 'AKIAYWQTISJD6QXMAKY', 'Status': 'Active', 'CreateDate': datetime.datetime(2023, 1, 24, 12, 30, 59, tzinfo=tzutc())},
{'UserName': 'eee', 'AccessKeyId': 'AKIAYWQTISJDUARK6FV', 'Status': 'Active', 'CreateDate': datetime.datetime(2023, 1, 24, 16, 58, 38, tzinfo=tzutc())}
]
new_data = {}
for entry in data:
new_data.setdefault(entry["UserName"], []).append(
{k: v for k, v in entry.items() if k != "UserName"}
)
print(new_data)
Output (some fields hidden because I don't want to import those libraries in my repl, but they'll be there when you run it)
{'aaa': [{'AccessKeyId': 'AKIAYWQTISJD6X27YVK', 'Status': 'Active'}],
'eee': [{'AccessKeyId': 'AKIAYWQTISJD6QXMAKY', 'Status': 'Active'},
{'AccessKeyId': 'AKIAYWQTISJDUARK6FV', 'Status': 'Active'}]}
Related
I'm trying to narrow down list of dicts by filtering it by value in one of the keys.
Current codes does it but I don't know how to retain entire dictionary rather then only those fields I filter by.
final_list = []
jobs = [glue_client.job_status(e) for e in j]
for e in jobs:
for page in e:
final_list.append(page["JobRuns"])
flat_list = [item for sublist in final_list for item in sublist]
sorted_list = sorted(flat_list, key=lambda k: (k['JobName'], k['StartedOn']), reverse=True)
#need to have following keys: "JobName", "JobRunState", "StartedOn" and "Id"
latest_jobs = [
{'JobName': key, 'StartedOn': max(item['StartedOn'] for item in values)}
for key, values in groupby(flat_list, lambda dct: dct['JobName'])
]
print(latest_jobs)
Data at sorted_list variable looks as below:
list_of_dicts = [
{'JobName': 'a', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fail', 'id': 'xyz'},
{'JobName': 'a', 'StartedOn': datetime.datetime(2021, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'ok', 'id': 'xyz'},
{'JobName': 'b', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fail', 'id': 'xyz'},
{'JobName': 'a', 'StartedOn': datetime.datetime(2020, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fai;', 'id': 'xyz'},
{'JobName': 'b', 'StartedOn': datetime.datetime(2021, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'ok', 'id': 'xyz'}
]
Expected output:
filtered_list = [
{'JobName': 'a', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fail', 'id': 'xyz'},
{'JobName': 'b', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000, tzinfo=tzlocal()), 'JobRunState': 'fail', 'id': 'xyz'}
]
Some judicious use of itertools.groupby, sorted, and max.
list_of_dicts = [
{'JobName': 'a', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000), 'JobRunState': 'fail', 'id': 'xyz'},
{'JobName': 'a', 'StartedOn': datetime.datetime(2021, 10, 18, 13, 0, 47, 306000), 'JobRunState': 'ok', 'id': 'xyz'},
{'JobName': 'b', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000), 'JobRunState': 'fail', 'id': 'xyz'},
{'JobName': 'a', 'StartedOn': datetime.datetime(2020, 10, 18, 13, 0, 47, 306000), 'JobRunState': 'fai;', 'id': 'xyz'},
{'JobName': 'b', 'StartedOn': datetime.datetime(2021, 10, 18, 13, 0, 47, 306000), 'JobRunState': 'ok', 'id': 'xyz'}
]
from itertools import groupby
from operator import itemgetter
lst = sorted(list_of_dicts, key=itemgetter('JobName'))
[max(jobs, key=itemgetter('StartedOn'))
for jn, jobs in groupby(lst, key=itemgetter('JobName'))]
# [{'JobName': 'a', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000), 'JobRunState': 'fail', 'id': 'xyz'},
# {'JobName': 'b', 'StartedOn': datetime.datetime(2022, 10, 18, 13, 0, 47, 306000), 'JobRunState': 'fail', 'id': 'xyz'}]
I have two lists (with dicts in it):
old_device_data_list = [{'_id': ObjectId('5f48c8e34545fac49fbff5'), 'device_id': 5, 'time': datetime.datetime(2020, 8, 26, 9, 5, 39, 827000), 'values': {'count': 100, 'late': 0, 'max': 0, 'min': 0, 'on_time': 100, 'sum': 100}}]
result = [{'_id': ObjectId('5f48c8e3997640fac49fbff5'), 'device_id': 5, 'time': datetime.datetime(2020, 8, 26, 9, 5, 39, 827000), 'values': {'count': 100, 'late': 0, 'max': 0, 'min': 0, 'on_time': 100, 'sum': 100}}, {'_id': ObjectId('5f48c8e3997640fac49fbff6'), 'device_id': 4, 'time': datetime.datetime(2020, 8, 26, 9, 5, 39, 827000), 'values': {'count': 180, 'late': 0, 'max': 0, 'min': 0, 'on_time': 180, 'sum': 180}}, {'_id': ObjectId('5f48c8e3997640fac49fbff8'), 'device_id': 3, 'time': datetime.datetime(2020, 8, 27, 9, 5, 39, 827000), 'values': {'count': 50, 'late': 0, 'max': 0, 'min': 0, 'on_time': 50, 'sum': 50}}, {'_id': ObjectId('5f48c8e3997640fac49fbff7'), 'device_id': 4, 'time': datetime.datetime(2020, 8, 27, 9, 5, 39, 827000), 'values': {'count': 120, 'late': 0, 'max': 0, 'min': 0, 'on_time': 120, 'sum': 120}}, {'_id': ObjectId('5f48c8e3997640fac49fbff9'), 'device_id': 3, 'time': datetime.datetime(2020, 8, 28, 9, 5, 39, 827000), 'values': {'count': 210, 'late': 0, 'max': 0, 'min': 0, 'on_time': 210, 'sum': 210}}]
I want to delete the dicts from the old_device_data_list out of the result list. I tried it with numpy with:
numpy.setdiff1d(result, old_device_data_list)
Then I got error:
TypeError: '<' not supported between instances of 'dict' and 'dict'
The description of numpy.setdiff1d says:
Return the sorted, unique values in ar1 that are not in ar2.
In order to sort the values, it needs to compare them using the < operator. But dictionaries cannot be compared like this. The relation "smaller than" is not defined for dictionaries.
NumPy is designed for working with numeric values, not for arbitrary Python data structures.
You could use a simple list comprehension to create a list of those dictionaries that are in result but not in old_device_data_list:
result = [d for d in result if d not in old_device_data_list]
This question already has answers here:
Convert Django Model object to dict with all of the fields intact
(17 answers)
Closed 3 years ago.
How to get current user's properties into dict format like given below... I tried request.user.__dict__ and request.user.__class__.__dict__ but not giving that data
{
'_state': < django.db.models.base.ModelState object at 0x7fa2c8a14da0 > ,
'id': 1,
'password': 'gVFDqqWHxJhnrkyYANJb',
'last_login': None,
'is_superuser': False,
'username': 'ualexander',
'first_name': 'Valerie',
'last_name': 'Jones',
'email': 'gonen#yahoo.com',
'is_staff': False,
'is_active': True,
'date_joined': datetime.datetime(2019, 4, 6, 10, 52, 24, 142211, tzinfo = < UTC > )
}
views.py
def dashboard_view(request):
print(request.user.__dict__)
my output
{'_setupfunc': <function AuthenticationMiddleware.process_request.<locals>.<lambda> at 0x7fe71c6bfea0>, '_wrapped': <User: nitin>}
You can do this.
request.user.__class__.objects.filter(pk=request.user.id).values().first()
It will return sample output like this
{'id': 1, 'last_login': datetime.datetime(2019, 4, 5, 10, 44, 19, 110212, tzinfo=<UTC>), 'is_superuser': True, 'username': 'example', 'first_name': 'first', 'last_name': 'last', 'is_staff': True, 'is_active': True, 'date_joined': datetime.datetime(2019, 4, 5, 9, 31, 16, 736841, tzinfo=<UTC>), 'created_at': datetime.datetime(2019, 4, 5, 9, 31, 16, 962971, tzinfo=<UTC>), 'modified_at': datetime.datetime(2019, 4, 5, 9, 31, 16, 962992, tzinfo=<UTC>), 'deleted_at': None, 'is_deleted': False, 'user_id': 1, 'password': 'pbkdf2_sha256$150000$JDcvyHbn1aFI$8gzgVZP/+bvZVQ/OISSF/+BJcJuAJE7zGU4rpBVpA8M=', 'email': 'examle#gmail.com', 'member_from': datetime.date(2019, 1, 1), 'phone_number': '011111111'}
Update:
You want to get objects as dictionary for request user.
In django request.user not give you data as dict format
To get your desired result, You need to do some tricky task.
request.user.__class__.objects.filter(pk=request.user.id).values().first()
here request.user.__class__ is result the model name, then filter this with current user.
I have a django view that I need to query from different models and combine them, and then organize by date ('created_at'), right now when combining the models I get a list of dicts like below. How can I sort this by date.
[{'content': u'Just another another message', 'created_at':
datetime.datetime(2018, 4, 22, 15, 35, 11, 577175, tzinfo=<UTC>),
u'successmatch_id': 5, u'id': 8, 'reciever': u'UserA'},
{'content': u'testing blah', 'created_at': datetime.datetime(2018, 4,
22, 15, 33, 28, 84469, tzinfo=<UTC>), u'successmatch_id': 5, u'id': 7,
'reciever': u'UserB'}, {'content': u'Hi how are you',
'created_at': datetime.datetime(2018, 4, 22, 13, 29, 49, 516701,
tzinfo=<UTC>), u'successmatch_id': 5, u'id': 6, 'reciever':
u'UserA'}]
Python's built-in sorting has the ability to specify what metric to sort by:
x = [{"test": 1}, {"test": 2}, {"test": 0}]
x.sort(key=lambda item: item["test"])
x is edited in place, and is now:
[{'test': 0}, {'test': 1}, {'test': 2}]
So, in your case, assuming your list is called my_list, you'd want to do:
my_list.sort(key=lambda item: item["created_at"])
Or, if you wanted the newest dicts to occur first,
my_list.sort(key=lambda item: item["created_at"], reverse=True)
If you are happy using a 3rd party library, you can use pandas, which accepts a list of dictionaries.
But note that datetime objects may be converted to pandas.Timestamp objects.
import pandas as pd
import datetime
lst = [{'content': u'Just another another message',
'created_at': datetime.datetime(2018, 4, 22, 15, 35, 11, 577175, tzinfo=None),
u'successmatch_id': 5, u'id': 8, 'reciever': u'UserA'},
{'content': u'testing blah',
'created_at': datetime.datetime(2018, 4, 22, 15, 33, 28, 84469, tzinfo=None),
u'successmatch_id': 5, u'id': 7, 'reciever': u'UserB'},
{'content': u'Hi how are you',
'created_at': datetime.datetime(2018, 4, 22, 13, 29, 49, 516701, tzinfo=None),
u'successmatch_id': 5, u'id': 6, 'reciever': u'UserA'}]
res = pd.DataFrame(lst).sort_values('created_at').T.to_dict().values()
Result:
dict_values([{'content': 'Hi how are you', 'created_at': Timestamp('2018-04-22 13:29:49.516701'),
'id': 6, 'reciever': 'UserA', 'successmatch_id': 5},
{'content': 'testing blah', 'created_at': Timestamp('2018-04-22 15:33:28.084469'),
'id': 7, 'reciever': 'UserB', 'successmatch_id': 5},
{'content': 'Just another another message', 'created_at': Timestamp('2018-04-22 15:35:11.577175'),
'id': 8, 'reciever': 'UserA', 'successmatch_id': 5}])
I have below input list of dictionaries
inpdata = {"cat": [{"categories": [{"cid": 27}, {"cid": 66}, {"cid": 29}], "id": 20},
{"categories": [{"cid": 66}], "id": 21},
{"categories": [{"cid": 66}, {"cid": 27}], "id": 22},
{"categories": [{"cid": 66}, {"cid": 27}], "id": 23},
{"categories": [{"cid": 66}, {"cid": 29}, {"cid": 27}], "id": 24}]};
Am trying to get the count of id's for each cid along with the id values, I used below code for that -
allcategories = set( sec['cid'] for record in inpdata['cat'] for sec in record['categories'] )
summarize = lambda record: record['id']
fs_cat = [
{
'cat':cid,
'count':len(matches),
'ids':[ summarize( match ) for match in matches ]
}
for cid in allcategories
for matches in [[
record for record in inpdata['cat'] if cid in [ sec['cid'] for sec in record['categories'] ]
]]
]
print(fs_cat)
This gives the output as -
[{'cat': 66, 'count': 5, 'ids': [20, 21, 22, 23, 24]},
{'cat': 27, 'count': 4, 'ids': [20, 22, 23, 24]},
{'cat': 29, 'count': 2, 'ids': [20, 24]}
]
But how can I get the combination of the categories {66,27,29} ?
I tried using below approach for getting the combinations of this input - it gives the combination of items from the list
allcategories = {66,27,29}
for subset in itertools.chain.from_iterable(itertools.combinations(allcategories, n) for n in range(len(allcategories) + 1)):
print(subset)
But I couldn't figure out how can I use this approach to get me the result as below for categories {66,27,29} from the 'inpdata'
result=[{'cat': '66', 'count': 5, 'ids': [20, 21, 22, 23, 24]},
{'cat': '27', 'count': 4, 'ids': [20, 22, 23, 24]},
{'cat': '29', 'count': 2, 'ids': [20, 24]},
{'cat': '66&27', 'count': 4, 'ids': [20, 22, 23, 24]},
{'cat': '66&29', 'count': 2, 'ids': [20, 24]},
{'cat': '27&29', 'count': 2, 'ids': [20, 24]},
{'cat': '66&27&29', 'count': 2, 'ids': [20, 24]}
]
Could you please suggest on how I can achieve this?
itertools.combinations(1), itertools.combinations(2), ... upto itertools.combinations(n) will give you all combinations of fs_cat (where, n = len(fs_cat))
import itertools
import operator
from functools import reduce
fs_cat = [
{'cat': 66, 'count': 5, 'ids': [20, 21, 22, 23, 24]},
{'cat': 27, 'count': 4, 'ids': [20, 22, 23, 24]},
{'cat': 29, 'count': 2, 'ids': [20, 24]},
]
result = []
for n in range(1, len(fs_cat) + 1): # 1, 2, ..., len(fs_cat)
for xs in itertools.combinations(fs_cat, n):
cat = '&'.join(map(str, sorted(x['cat'] for x in xs)))
ids = sorted(reduce(operator.and_, (set(x['ids']) for x in xs)))
result.append({'cat': cat, 'count': len(ids), 'ids': ids})
>>> result
[{'cat': '66', 'count': 5, 'ids': [20, 21, 22, 23, 24]},
{'cat': '27', 'count': 4, 'ids': [20, 22, 23, 24]},
{'cat': '29', 'count': 2, 'ids': [20, 24]},
{'cat': '27&66', 'count': 4, 'ids': [20, 22, 23, 24]},
{'cat': '29&66', 'count': 2, 'ids': [20, 24]},
{'cat': '27&29', 'count': 2, 'ids': [20, 24]},
{'cat': '27&29&66', 'count': 2, 'ids': [20, 24]}]