Find absents dictionaries in a list of it - list

I need to compare two lists of dictionaries and retrieve the absence elements, "connection" is the attribute who identify the object. The other properties may vary in time. I tried with filters and map but I'm still stuck.
input should look like this:
list1 = [{'username': 'user1', 'connection': "0x2083588'", 'remote': '10.0.5.251:44840','uri': 'www.google.com:443','seconds': '600'}
,{'username': 'user2', 'connection': "0x2a90d778'", 'remote': '10.0.5.251:44796','uri': 'mobilenetworkscoring-pa.googleapis.com:443','seconds': '600'}]
list2 = [{'username': 'user1', 'connection': "0x2083588'", 'remote': '10.0.5.251:44840','uri': 'www.google.com:443','seconds': '400'}
,{'username': 'user2', 'connection': "0x2a90d778'", 'remote': '10.0.5.251:44796','uri': 'mobilenetworkscoring-pa.googleapis.com:443','seconds': '400'}
,{'username': 'user3', 'connection': "0x2a90d678'", 'remote': '10.0.5.251:44796','uri': 'mobilenetworkscoring-pa.googleapis.com:443','seconds': '400'}]
the output should be like this:
[{'username': 'user3', 'connection': "0x2a90d678'", 'remote': '10.0.5.251:44796','uri': 'mobilenetworkscoring-pa.googleapis.com:443','seconds': '400'}]

# Mapping the list1 by "connection" property
mapList = map(lambda y: y.get('connection'), list1)
# Filtering the elements of the second list (list2)
# that are missing from the map of the list1 (mapList) by "connection" property
filterList = filter(lambda x: x.get('connection') not in mapList,list2)
print filterList

Related

Extract key values from multiple lists of dictionaries python

I have multiple empty lists and dict in side list. I need to extract dict key values in list.
Example:
l =([{'COUNTRY': 'UK', 'STUDENT': 'JOHN'}, {'COUNTRY': 'PT', 'STUDENT':'PEDRO'}, {'COUNTRY': 'UK', 'STUDENT': 'KYLE'}, {'COUNTRY': 'IT', 'STUDENT':'PIRLO'}, {'COUNTRY': 'PT', 'STUDENT':'ANA'}, {'COUNTRY': 'FR', 'STUDENT':'VITO'}, {'COUNTRY': 'FR', 'STUDENT':'LOUIS'}, [], []])
expected result:
k = ['UK', 'PT', 'UK', 'IT', 'PT', 'FR', 'FR']

Serialize Django Request

I'd like to serialize the Django request in order to log it in a DB. I tried different approaches but none of them successfully.
class RunTest(View):
def get(self, request, url):
srd = serializers.serialize('json', request)
return HttpResponse(json.dumps(request.META))
But this raise the error
module 'rest_framework.serializers' has no attribute 'serialize'
Probably because I'm using the rest-framework as a Middleware.
I also used
srd = json.dumps(request)
In this case the error is
Object of type 'WSGIRequest' is not JSON serializable
Any ideas how to fix this?
I've faced similar problem when trying to store received requests META data in JSONField. Problem is that request.META is a dict but it's not appropriate JSON.
Example request.META I have is:
{
"wsgi.version": (1, 0),
"wsgi.url_scheme": "http",
"wsgi.input": <_io.BufferedReader name=10>,
"wsgi.errors": <_io.TextIOWrapper name="<stderr>" mode="w" encoding="utf-8">,
"wsgi.multithread": True,
"wsgi.multiprocess": False,
"wsgi.run_once": False,
"SERVER_SOFTWARE": "Werkzeug/1.0.1",
"REQUEST_METHOD": "POST",
"SCRIPT_NAME": "",
"PATH_INFO": "/api/v1/vouchers/voucher-distribute/",
"QUERY_STRING": "",
"REQUEST_URI": "/api/v1/vouchers/voucher-distribute"
...
}
So as you can see first few keys with wsgi prefix is inappropriate JSON format what you can also check online at: http://json.parser.online.fr/
So to store request.META as JSON dict it's necessary to get rid of this keys. The trick is that you cannot use request.META.pop("wsgi.version") because request.META is not appropriate JSON format :)
What I did is I've created helper function:
def create_request_meta_json_object(meta_data):
return {
"REQUEST_METHOD": meta_data["REQUEST_METHOD"],
"SERVER_SOFTWARE": meta_data["SERVER_SOFTWARE"],
"REQUEST_METHOD": meta_data["REQUEST_METHOD"],
"SCRIPT_NAME": meta_data["SCRIPT_NAME"],
"PATH_INFO": meta_data["PATH_INFO"],
"QUERY_STRING": meta_data["QUERY_STRING"],
"REQUEST_URI": meta_data["REQUEST_URI"],
"RAW_URI": meta_data["RAW_URI"],
"REMOTE_ADDR": meta_data["REMOTE_ADDR"],
"REMOTE_PORT": meta_data["REMOTE_PORT"],
"SERVER_NAME": meta_data["SERVER_NAME"],
"SERVER_PORT": meta_data["SERVER_PORT"],
"SERVER_PROTOCOL": meta_data["SERVER_PROTOCOL"],
"HTTP_X_FORWARDED_HOST": meta_data["HTTP_X_FORWARDED_HOST"],
"HTTP_X_FORWARDED_PORT": meta_data["HTTP_X_FORWARDED_PORT"],
"HTTP_ACCEPT_ENCODING": meta_data["HTTP_ACCEPT_ENCODING"],
"HTTP_USER_AGENT": meta_data["HTTP_USER_AGENT"],
"HTTP_FROM": meta_data["HTTP_FROM"],
"HTTP_ACCEPT": meta_data["HTTP_ACCEPT"],
"CONTENT_TYPE": meta_data["CONTENT_TYPE"],
"CONTENT_LENGTH": meta_data["CONTENT_LENGTH"],
"HTTP_CONNECTION": meta_data["HTTP_CONNECTION"],
"HTTP_X_NGINX_PROXY": meta_data["HTTP_X_NGINX_PROXY"],
"HTTP_X_FORWARDED_PROTO": meta_data["HTTP_X_FORWARDED_PROTO"],
"HTTP_X_FORWARDED_FOR": meta_data["HTTP_X_FORWARDED_FOR"],
"HTTP_X_REAL_IP": meta_data["HTTP_X_REAL_IP"],
}
and use it like:
meta_data_as_json = create_request_meta_json_object(request.META)
You cannot serialize request - you could serialize request.GET also know as request.query_paramsin DRF.
srd = json.dumps(request.query_params)
or
srd = json.dumps(request.GET)
To use a serializer, you first have to create one. Declaring Serializers is a good starting point.
Another potential solution is to use dictionary comprehension:
meta_keys = {
"wsgi.version": (1, 0),
"wsgi.version": "http",
"wsgi.input": object(),
"wsgi.errors": object(),
"wsgi.multithread": True,
"wsgi.multiprocess": False,
"wsgi.run_once": False,
"SERVER_SOFTWARE": "Werkzeug/1.0.1",
"REQUEST_METHOD": "POST",
"SCRIPT_NAME": "",
"PATH_INFO": "/api/v1/vouchers/voucher-distribute/",
"QUERY_STRING": "",
"REQUEST_URI": "/api/v1/vouchers/voucher-distribute"
}
excluded_meta_keys = ['wsgi.version', 'wsgi.version', 'wsgi.input', 'wsgi.multithread', 'wsgi.multiprocess', 'wsgi.run_once', 'wsgi.errors']
print({key: value for key, value in meta_keys.items() if key not in excluded_meta_keys})
print({key: value for key, value in meta_keys.items() if isinstance(value, (str, bool, int, float))})
results in:
{'SERVER_SOFTWARE': 'Werkzeug/1.0.1', 'REQUEST_METHOD': 'POST', 'SCRIPT_NAME': '', 'PATH_INFO': '/api/v1/vouchers/voucher-distribute/', 'QUERY_STRING': '', 'REQUEST_URI': '/api/v1/vouchers/voucher-distribute'}
{'wsgi.version': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.run_once': False, 'SERVER_SOFTWARE': 'Werkzeug/1.0.1', 'REQUEST_METHOD': 'POST', 'SCRIPT_NAME': '', 'PATH_INFO': '/api/v1/vouchers/voucher-distribute/', 'QUERY_STRING': '', 'REQUEST_URI': '/api/v1/vouchers/voucher-distribute'}
respectively
request.META has keys of types not allowed by a json object, so you can generate another dictionary only with keys with values of str type:
dict = create_request_meta_json_object(request.META)
def create_request_meta_json_object(meta_data):
diccionario = []
for key, value in meta_data.items():
if type(value) is str:
diccionario.append({"key": key, "value": value})
return diccionario

List comprehension to make a list of values in a nested dictionary

I'm given this nested dictionary (albeit a bit longer):
stuff = [{'10525083': {'ID': '10525083', 'Score': 25, 'Name': 'Alia Lightside', 'Responses': {'....},
'11004337': {'ID': '11004337', 'Score': 24, 'Name': 'Keebo Keempo', 'Responses': {'....}}]
I need to take all the values relating to the 'Score' key and put them in a list... using list comprehension.
I think it should be something like this but I'm really just throwing stones:
score = [k, v for v in stuff -something something- append? ]
[v.get('Score') for k, v in stuff.items() ]

How can I merge two or more dictionaries in a list?

Is there any nice pythonic way of merging dictionaries within a list?
What I have:
[
{ 'name': "Jack" },
{ 'age': "28" }
]
What I would like:
[
{ 'name': "Jack", 'age': "28" }
]
Here's a method that uses dict.update(). In my opinion it's a very readable solution:
data = [{'name': 'Jack'}, {'age': '28'}]
new_dict = {}
for d in data:
new_dict.update(d)
new_data = [new_dict]
print new_data
OUTPUT
[{'age': '28', 'name': 'Jack'}]
If you're using Python 3, you can use collections.ChainMap:
>>> from collections import ChainMap
>>> ld = [
... { 'name': "Jack" },
... { 'age': "28" }
... ]
>>> [dict(ChainMap(*ld))]
[{'name': 'Jack', 'age': '28'}]
You could use list comprehension:
final_list = [{key: one_dict[key]
for one_dict in initial_list
for key in one_dict.keys()}]
Edit: the list comprehension was backwards
out = reduce(lambda one, two: dict(one.items() + two.items()),
[{'name': 'Jack'}, {'age': '28'}, {'last_name': 'Daniels'}])
print(out)
OUTPUT
{'age': '28', 'last_name': 'Daniels', 'name': 'Jack'}

How can I put the elements in a list into a dictionary in Python

I have a list:
txtlst = [
['000001', 'DOE', 'JOHN', 'COMSCI', '', 'MATH', '', 'ENGLISH\n'],
['000002', 'DOE', 'JANE', 'FRENCH', '', 'MUSIC', '', 'COMSCI\n']
]
And I want to put the elements in a dictionary so it looks likes this
mydict = {
'000001': ['000001', 'DOE', 'JOHN', 'COMSCI', '', 'MATH', '', 'ENGLISH\n'],
'000002': ['000002', 'DOE', 'JANE', 'FRENCH', '', 'MUSIC', '', 'COMSCI\n']
}
My problem here is, after I ran the code
for i in txtlst:
key = i[0]
value = i
mydict = {key:value}
The two sublists of txtlst are added to different dictionaries. How can I fix my code so they will be in the same dictionary as I mentioned above?
You can easily create a new dictionary with the first element of each list as key:
mydict = { i[0]: i for i in txtlst }
If you wish to do that in a loop like in your approach, you need to initialize a dictionary beforehand and update it in each iteration:
mydict = {}
for i in txtlst:
key = i[0]
value = i
mydict[key] = value