I have below dictionaries of lists:
dict1 = {'SourceName': ['PUICUI'], 'EventType': ['XYX'], 'TableName': ['XYX__ct'], 'KeyIndex': ['XYX', 'ZXX']}
dict2 = {'SourceName': ['PUICI2'], 'EventType': ['XYX'], 'TableName': ['ZXX__ct1']}
And my below piece of code is working just as expected.
def combineDictList(*args):
result = {}
for dic in args:
for key in (result.keys() | dic.keys()):
if key in dic:
result.setdefault(key, []).extend(dic[key])
return result
print(combineDictList(dict1, dict2))
which gives me
{'TableName': ['XYX__ct', 'ZXX__ct1'], 'SourceName': ['PUICUI', 'PUICI2'], 'KeyIndex': ['XYX', 'ZXX'], 'EventType': ['XYX', 'XYX']}
But my question is how to print the final result to have unique values, e.g. here EventType has same values.
So, in final result i would only expect the final result to be
{'TableName': ['XYX__ct', 'ZXX__ct1'], 'SourceName': ['PUICUI', 'PUICI2'], 'KeyIndex': ['XYX', 'ZXX'], 'EventType': ['XYX']}
Is there anyway I can achieve this?
Try this
def combineDictList(*args):
result = {}
for dic in args:
for key in (result.keys() | dic.keys()):
if key in dic:
result.setdefault(key, []).extend(dic[key])
result[key] = list(set(result[key]))
return result
print(combineDictList(dict1, dict2))
Use set
Ex:
dict1 = {'SourceName': ['PUICUI'], 'EventType': ['XYX'], 'TableName': ['XYX__ct'], 'KeyIndex': ['XYX', 'ZXX']}
dict2 = {'SourceName': ['PUICI2'], 'EventType': ['XYX'], 'TableName': ['ZXX__ct1']}
def combineDictList(*args):
result = {}
for dic in args:
for k, v in dic.items():
result.setdefault(k, set()).update(v)
# If you need values as list
# result = {k: list(v) for k, v in result.items()}
return result
print(combineDictList(dict1, dict2))
Output:
{'EventType': {'XYX'},
'KeyIndex': {'ZXX', 'XYX'},
'SourceName': {'PUICI2', 'PUICUI'},
'TableName': {'ZXX__ct1', 'XYX__ct'}}
Related
I want to create python dictionary something like below
{"Disk1" : "deva", "Disk2" :"devb" , "Disk3": "devc" .....}
How can I create the above dictionary without defining all vales statically
You can create an empty dictionary and add the keys/values later:
my_dict = {}
key = "abc"
value = 123
my_dict[key] = value
Do the following :
def disck():
g = {}
for i in range(1,27):
f = 'Disck'+str(i)
j = 'dev'+ chr(97+i-1)
g.update({f:j})
return g
If you know the keys in advance, it can be done as:
from collections import defaultdict
def add_to_dict(key, value, dict):
dict[key] = value
out = defaultdict(str)
out['Disk1'] = ''
out['Disk2'] = ''
add_to_dict('Disk1', 'deva', out)
add_to_dict('Disk2', 'devb', out)
print (out)
Output:
defaultdict(<class 'str'>, {'Disk1': 'deva', 'Disk2': 'devb'})
I'm looking to take a log file in the following format and turn it into the json format of the snippet below.
2020:03:29-23:07:22 sslvpnpa ulogd[19880]: id="2001" severity="info" sys="SecureNet" sub="packetfilter" name="Packet dropped" action="drop" fwrule="60001" initf="eth0"
and turn it into the json format of the snippet below.
{"timestamp": "2020:03:29-23:07:22", "object": "sslvpnpa", "code": "ulogd[19880]", "id":"2001", severity="info", sys="SecureNet", sub="packetfilter" ...}
My start was to loop like this:
log_fields = log_row.split()
obj={}
for k in log_fields:
if k.find('=') > -1:
obj[k.split('=')[0]] = k.split('=')[1]
But then i realized some of the values have spaces and that there might be some list comprehension or generator expression that is more efficient or easier to read.
The object/json this generates will then be added to a field in a larger object.
Thanks in advance.
I think this will work out for you:
def split_string(s):
d = {}
ind = 0
split_s = s.split()
while ind < len(split_s):
current_s = split_s[ind]
if "=" in current_s:
key, value, ind = get_full_string(split_s, ind)
d[key] = value
else:
d[f"key{ind}"] = current_s
ind += 1
return d
def get_full_string(split_s, ind):
current_s = split_s[ind]
current_s_split = current_s.split("=")
key = current_s_split[0]
current_value = current_s_split[1]
if current_value[-1] == '"':
current_value = current_value.replace('"', '')
return key, current_value, ind
value_list = [current_value]
ind += 1
while ind < len(split_s):
current_value = split_s[ind]
value_list.append(current_value)
if current_value[-1] == '"':
break
ind += 1
value = " ".join(value_list)
value = value.replace('"', '')
return key, value, ind
Input:
s = '2020:03:29-23:07:22 sslvpnpa ulogd[19880]: id="2001" severity="info" sys="SecureNet" sub="packetfilter" name="Packet dropped" action="drop" fwrule="60001" initf="eth0"'
print(split_string(s))
Output:
{'key0': '2020:03:29-23:07:22', 'key1': 'sslvpnpa', 'key2': 'ulogd[19880]:', 'id': '2001', 'severity': 'info', 'sys': 'SecureNet', 'sub': 'packetfilter', 'name': 'Packet dropped', 'action': 'drop', 'fwrule': '60001', 'initf': 'eth0'}
I have list
keywords = ['car','bike','motorcycle', 'airplane', 'boat', 'boat']
and I have a api that returns data
[('bike','http://bikes.com/bikes'),
('boat':'http://boat.com/boat')]
so I need a tuple/list which can be like
[('car','none'),
('bike','http://bikes.com/bikes'),
('motorcycle','none'),
('airplane','none'),
('boat','http://boat.com/boat'),
('boat','http://boat.com/boat')]
Basically I was able to create with dictionary how ever I wanted to retain duplicates.
keyword_list = keyword.split(",")
response = requests.request("GET", url, headers=headers, params=querystring)
field_json = json.loads(response.text)
data = field_json['response']
field_json = json.loads(response.text)
data = field_json['response']
if len(data)> 0:
list1 = {}
for i in data['docs']:
list1[i['keyword_s']]= i['url_s']
print(list(list1.items()))
keyword_dict = {k: None for k in keyword_list}
keyword_dict.update(list1)
return keyword_dict
Your code:
keywords = ['car','bike','motorcycle', 'airplane', 'boat', 'boat']
api = [('bike','http://bikes.com/bikes'), ('boat', 'http://boat.com/boat')]
Solution:
api_dict = dict(api)
out = [api_dict.get(k) for k in keywords]
api = [('bike','http://bikes.com/bikes'),
('boat','http://boat.com/boat')]
keywords = ['car','bike','motorcycle', 'airplane', 'boat', 'boat']
ans = []
missing = set(keywords)
for k, v in api:
if k in keywords:
ans.append((k, v))
missing.remove(k)
for miss in missing:
ans.append((miss, None))
print(ans)
I set up a class of collection, and I created an object containing a dictionary.
I created a method called pluck(self, key) that should return a new Collection with all the values of the key I sent, and I'm used with another method's that I created before (map and filter - Both methods of collection).
class Collection(object):
def __init__(self,iterable = None):
# param iterable: imutable collection
if iterable == None:
self.Iterable = ()
else:
self.Iterable = tuple(iterable)
return None
def map(self, *callbacks):
'''
:param callbacks: List of function to apply on each element in 'self.Iterable'
:return: New mapped collection
'''
c =Collection(self.Iterable)
tmp = Collection()
for item in callbacks:
for item2 in c.Iterable:
tmp = tmp.append(item(item2))
c = Collection(tmp.Iterable)
return c
def filter(self, *callbacks):
'''
:param callbacks: List of function to apply on each element in 'self.Iterable'
:return: New filtered collection
'''
return Collection(item for item in self.Iterable if CallbacksFilter(item, callbacks) == True)
def CallbacksFilter(item, callback):
for f in callback:
if f(item) == False:
return False
return True
when I try to run pluck method:
def pluck(self, key):
return self.values() if type(self.first()) is not dict else Collection(self.Iterable).filter(self.map(lambda x, y: dict([(i,x[i]) for i in x if i in set(y)])))
c3 = Collection([{'name': 'Joe', 'age': 20}, {'name': 'Jane', 'age': 13}])
c3.pluck('age')
I expect to output " Collection(20,13)" but I'm getting this error:
TypeError: () missing 1 required positional argument: 'y'
How can I fix this error?
Note: If the internal elements are not dictionaries, then a copy of the current collection returned.
The method I wrote is incorrect and does not return any result, as I mentioned above.
def pluck(self, key):
return self.values() if type(self.first()) is not dict else Collection(self.Iterable).filter(self.map(lambda x, y: dict([(i,x[i]) for i in x if i in set(y)])))
The Map method returns the result by applying the lambda function given to it on each dictionary of the collection.
def map(self, *callbacks):
'''
:param callbacks: List of function to apply on each element in 'self.Iterable'
:return: New mapped collection
'''
c =Collection(self.Iterable)
tmp = Collection()
for item in callbacks:
for item2 in c.Iterable:
tmp = tmp.append(item(item2))
c = Collection(tmp.Iterable)
return c
So when we run the following code:
def pluck(self, key):
'''
:param key: Dictionary key (13)
:return: Return a new Collection with value of each key.
'''
return "Collection{}".format(Collection(self.map(lambda index: index[key])).Iterable)
c3 = Collection([{'name': 'Joe', 'age': 20}, {'name': 'Jane', 'age': 13}])
c3.pluck('age')
we get the right result:
Collection(20,13)
I have a deeply nested dict and need to iterate through it and return the value corresponding to the key argument, second argument of my function.
For example, with
tree = {"a": 12, "g":{ "b": 2, "c": 4}, "d":5}
tree_traverse(tree, "d") should return 5
Here is my code:
def tree_traverse(tree, key):
for k,v in tree.items():
if isinstance(v, dict):
tree_traverse(v, key)
elif k == key:
return v
The problem I have is that this function returns None if it doesnt find the matching key once it's done iterating through the deepest nested dict.
I don't want it to return anything before the matching key is found.
I didn't find a solution in another thread, most of them use print statements and don't return anything so I guess it avoids this issue.
You have to check whether the recursive call actually found something so you can continue the loop. E.g. try the following:
def tree_traverse(tree, key):
if key in tree:
return tree[key]
for v in filter(dict.__instancecheck__, tree.values()):
if (found := tree_traverse(v, key)) is not None:
return found
Here we instantiate an object when the function is created, that all executions of the function will share, called _marker. We return this object if we don't find the key. (You could also use None here, but None is frequently a meaningful value.)
def tree_traverse(tree, key, *, _marker=object()):
for k,v in tree.items():
if isinstance(v, dict):
res = tree_traverse(v, key, _marker=_marker)
if res is not _marker:
return res
elif k == key:
return v
return _marker
def find(tree, key):
_marker = object()
res = tree_traverse(tree, key, _marker=_marker)
if res is _marker:
raise KeyError("Key {} not found".format(key))
return res
I use tree_traverse as a helper function because we want different behaviour at the outermost layer of our recursion (throw an error) than we want inside (return a _marker object)
A NestedDict can solve the problem
from ndicts import NestedDict
def tree_traverse(tree, k):
nd = NestedDict(tree)
for key, value in nd.items():
if k in key:
return value
>>> tree = {"a": 12, "g":{ "b": 2, "c": 4}, "d":5}
>>> tree_traverse(tree, "d")
5
To install ndicts pip install ndicts