Tying multiple dictionary entries to one key - python

I have some code that I am writing, and it is trying to imitate what an API call does. However there are multiple entries that can be put in the API call that have the same keys. For example, if you look at my call to the method, there are multiple names[] that are passed as part of the API call.
names[]": ["System/CPU/User/percent", "System/CPU/System/percent"]
Here is the code that have -
def new_relic_api(api_key, query_function, datapoints):
temp = {}
if (datapoints != None):
for k, v in datapoints.iteritems():
if isinstance(v, list):
for s in v:
print (k)
print s
temp[k] = s
else:
print k
print v
temp[k] = v
r = requests.get(url, headers=headers, data=temp)
d = {"names[]": ["System/CPU/User/percent", "System/CPU/System/percent"], "values[]": "average_value", 'from': '2016-11-30T18:31:00+00:00', 'to': '2016-11-30T19:01:00+00:00', 'summarize': 'true'}
new_relic_api("${api_key}", "/servers/{server_id}/metrics/data.json", d)
However, the actual dictionary is only printing out the second names[] value inside of the requests call. How can I fix this?
Thanks

That's because you write into dictionary temp in line temp[k] = s different values from "names[]" but with the same key:
items = {}
k = "names[]"
for s in ["System/CPU/User/percent", "System/CPU/System/percent"]:
items[k] = s
# items == {"name[]": "System/CPU/System/percent"}
It means that last value of s rewrites items[k] and items will always keep only one (last) value of names[].
Another thing is it's better to check if a value equals None with is operator:
if value is None: pass
if value is not None: pass
To pass both names[] values simultaneously you don't need to split its values, use requests.get and pass names[] as a list:
temp = {"names[]": ["System/CPU/User/percent", "System/CPU/System/percent"]}
r = requests.get(url, headers=headers, data=temp)
It will be requested as smth similar to:
url?names[]=System/CPU/User/percent&names[]=System/CPU/System/percent

Related

Python return key of dictionary depending on max value, but only where part of key = x

I have a dictionary in Python:
dict = {("s1", "a1"):1,("s1", "a2"):2,("s3", "a3"):3,("s1", "a3"):1}
Where key is a list(s, a) and value is an integer, so:
dict = {(s, a), i}
I want to pass in a specific s and return a where i is highest.
In the example above, I would expect to recieve "a2" if I passed in "s1".
So far I have the following:
print(max(dict, key=dict.get("s1"))[1])
However this is returning s3. How do I get this to work?
I would filter the dictionary first to only get items with a valid key and then find the key with the maximum value like this:
filtered_dict = {k:v for k, v in d.items() if k[0] == 's1'}
result = max(filtered_dict, key=filtered_dict.get)[1]
print(result)
Output:
a2
The structure of the data is not the ideal one for your given use-case. But if you have no other option, you need to visit every single element in the dict.
You visit each element once:
current_max = -999
result = None
for (k1,k2), value in dict.items():
if k1=="s1" and value > current_max:
result = k2
current_max = value

Python return key from value, but its a list in the dictionary

So Im quiet new to python and maybe I´ve searced the wrong words on google...
My current problem:
In python you can return the key to a value when its mentioned in a dictionary.
One thing I wonder, is it possible to return the key if the used value is part of a list of values to the key?
So my testing skript is the following
MainDict={'FAQ':['FAQ','faq','Faq']}
def key_return(X):
for Y, value in MainDict.items():
if X == value:
return Y
return "Key doesnt exist"
print(key_return(['FAQ', 'faq', 'Faq']))
print(key_return('faq'))
So I can just return the Key if I ask for the whole list,
How can I return the key if I just ask for one value of that list as written for the second print? On current code I get the "Key doesnt exist" as an answer.
You can check to see if a value in the dict is a list, and if it is check to see if the value you're searching for is in the list.
MainDict = {'FAQ':['FAQ','faq','Faq']}
def key_return(X):
for key, value in MainDict.items():
if X == value:
return key
if isinstance(value, list) and X in value:
return key
return "Key doesnt exist"
print(key_return(['FAQ', 'faq', 'Faq']))
print(key_return('faq'))
Note: You should also consider making MainDict a parameter that you pass to key_return instead of a global variable.
You can do this using next and a simple comprehension:
next(k for k, v in MainDict.items() if x == v or x in v)
So your code would look like:
MainDict = {'FAQ':['FAQ','faq','Faq']}
def key_return(x):
return next(k for k, v in MainDict.items() if x == v or x in v)
print(key_return(['FAQ', 'faq', 'Faq']))
#FAQ
print(key_return('faq'))
#FAQ
You can create a dict that maps from values in the lists to keys in MainDict:
MainDict={'FAQ':['FAQ','faq','Faq']}
back_dict = {value: k for k,values in MainDict.items() for value in values}
Then rewrite key_return to use this dict:
def key_return(X):
return back_dict[X]
print(key_return('faq'))
The line back_dict = {value: k for k,values in MainDict.items() for value in values} is a dictionary comprehension expression, which is equivalent to:
back_dict = {}
for k,values in MainDict.items():
for value in values:
back_dict[value] = k
This approach is more time-efficient that looping over every item of MainDict every time you search, since it only requires a single loopkup rather than a loop.

How to check that only one value of my dictionary is filled?

How can I check that my dict contains only one value filled ?
I want to enter in my condition only if the value is the only one in my dict and of this type (in my example "test2") of my dict.
For now I have this if statement
my_dict = {}
my_dict["test1"] = ""
my_dict["test2"] = "example"
my_dict["test3"] = ""
my_dict["test4"] = ""
if my_dict["test2"] and not my_dict["test1"] and not my_dict["test3"] and not my_dict["test4"]:
print("inside")
I would like to find a better, classy and "pep8" way to achieve that
Any ideas ?
You have to check every value for truthiness, there's no way around that, e.g.
if sum(1 for v in my_dict.values() if v) == 1:
print('inside')
You can use filter() as below to check how many values are there in the dictionary.
if len(list(filter(None, my_dict.values()))) == 1:
print("inside")
Assuming that all your values are strings, what about
ref_key = "test2"
if ''.join(my_dict.values()) == my_dict[ref_key]:
print("inside")
... since it looks like you have a precise key in mind (when you do if my_dict["test2"]). Otherwise, my answer is (twice) less general than (some) others'.
Maybe you want to check if there's only one pair in dictionary after removing the empty values.
my_dict = {}
my_dict["test1"] = ""
my_dict["test2"] = "example"
my_dict["test3"] = ""
my_dict["test4"] = ""
my_dict={key:val for key,val in my_dict.items() if val}
if len(my_dict)==1:
print("inside")
Here is the another flavour (without loops):
data = list(my_dict.values())
if data.count('') + 1 == len(data):
print("Inside")

i couldn't undestand what this lines of code do?

This part of class i did not understand what does do in this code:
for file in os.listdir(path):
if(os.path.isfile(os.path.join(path,file)) and select in file):
temp = scipy.io.loadmat(os.path.join(path,file))
temp = {k:v for k, v in temp.items() if k[0] != '_'}
for i in range(len(temp[patch_type+"_patches"])):
self.tensors.append(temp[patch_type+"_patches"][i])
self.labels.append(temp[patch_type+"_labels"][0][i])
self.tensors = np.array(self.tensors)
self.labels = np.array(self.labels)
especially this line :
temp = {k:v for k, v in temp.items() if k[0] != '_'}
the whole class is as follow :
class Datasets(Dataset):
def __init__(self,path,train,transform=None):
if(train):
select ="Training"
patch_type = "train"
else:
select = "Testing"
patch_type = "testing"
self.tensors = []
self.labels = []
self.transform = transform
for file in os.listdir(path):
if(os.path.isfile(os.path.join(path,file)) and select in file):
temp = scipy.io.loadmat(os.path.join(path,file))
temp = {k:v for k, v in temp.items() if k[0] != '_'}
for i in range(len(temp[patch_type+"_patches"])):
self.tensors.append(temp[patch_type+"_patches"][i])
self.labels.append(temp[patch_type+"_labels"][0][i])
self.tensors = np.array(self.tensors)
self.labels = np.array(self.labels)
def __len__(self):
try:
if len(self.tensors) != len(self.labels):
raise Exception("Lengths of the tensor and labels list are not the same")
except Exception as e:
print(e.args[0])
return len(self.tensors)
def __getitem__(self,idx):
sample = (self.tensors[idx],self.labels[idx])
# print(self.labels)
sample = (torch.from_numpy(self.tensors[idx]),torch.from_numpy(np.array(self.labels[idx])).long())
return sample
#tuple containing the image patch and its corresponding label
It's a dict comprehension; in this particular case, it creates a new dict from an existing dict temp, but only for items for which the key k does not start with an underscore. That check is performed by the if ... part.
It is equivalent to
new = {}
for k, v in temp.items():
if key[0] != '_':
new[k] = value
temp = new
or, slightly different:
new = {}
for key, value in temp.items():
if not key.startswith('_'):
new[key] = value
temp = new
You can see that it looks a bit nicer as a single line, since it avoids a temporary dict (new; under the hood, it still creates a nameless temporary dict though).
It is filtering out the underscore-prefixed variables from the loaded MATLAB file. From the scipy documentation the function scipy.io.loadmat returns a dictionary containing the variable names from the loaded file as keys and the matricies as values. The line of code you reference is a dictionary comprehension that clones the dictionary minus the variables that fail the conditional check.
Update
What happens here is roughly this:
Load a MATLAB file (file in your code) as a hashmap (dictionary) where the keys are the variable names from the file and the values are the matricies, assign to temp.
Iterate through those key/value pairs and drop the underscore-prefixed ones and reassign the results of that iteration to temp.
Profit

Finding matching keys in two large dictionaries and doing it fast

I am trying to find corresponding keys in two different dictionaries. Each has about 600k entries.
Say for example:
myRDP = { 'Actinobacter': 'GATCGA...TCA', 'subtilus sp.': 'ATCGATT...ACT' }
myNames = { 'Actinobacter': '8924342' }
I want to print out the value for Actinobacter (8924342) since it matches a value in myRDP.
The following code works, but is very slow:
for key in myRDP:
for jey in myNames:
if key == jey:
print key, myNames[key]
I've tried the following but it always results in a KeyError:
for key in myRDP:
print myNames[key]
Is there perhaps a function implemented in C for doing this? I've googled around but nothing seems to work.
Thanks.
Use sets, because they have a built-in intersection method which ought to be quick:
myRDP = { 'Actinobacter': 'GATCGA...TCA', 'subtilus sp.': 'ATCGATT...ACT' }
myNames = { 'Actinobacter': '8924342' }
rdpSet = set(myRDP)
namesSet = set(myNames)
for name in rdpSet.intersection(namesSet):
print name, myNames[name]
# Prints: Actinobacter 8924342
You could do this:
for key in myRDP:
if key in myNames:
print key, myNames[key]
Your first attempt was slow because you were comparing every key in myRDP with every key in myNames. In algorithmic jargon, if myRDP has n elements and myNames has m elements, then that algorithm would take O(n×m) operations. For 600k elements each, this is 360,000,000,000 comparisons!
But testing whether a particular element is a key of a dictionary is fast -- in fact, this is one of the defining characteristics of dictionaries. In algorithmic terms, the key in dict test is O(1), or constant-time. So my algorithm will take O(n) time, which is one 600,000th of the time.
in python 3 you can just do
myNames.keys() & myRDP.keys()
for key in myRDP:
name = myNames.get(key, None)
if name:
print key, name
dict.get returns the default value you give it (in this case, None) if the key doesn't exist.
You could start by finding the common keys and then iterating over them. Set operations should be fast because they are implemented in C, at least in modern versions of Python.
common_keys = set(myRDP).intersection(myNames)
for key in common_keys:
print key, myNames[key]
Best and easiest way would be simply perform common set operations(Python 3).
a = {"a": 1, "b":2, "c":3, "d":4}
b = {"t1": 1, "b":2, "e":5, "c":3}
res = a.items() & b.items() # {('b', 2), ('c', 3)} For common Key and Value
res = {i[0]:i[1] for i in res} # In dict format
common_keys = a.keys() & b.keys() # {'b', 'c'}
Cheers!
Use the get method instead:
for key in myRDP:
value = myNames.get(key)
if value != None:
print key, "=", value
You can simply write this code and it will save the common key in a list.
common = [i for i in myRDP.keys() if i in myNames.keys()]
Copy both dictionaries into one dictionary/array. This makes sense as you have 1:1 related values. Then you need only one search, no comparison loop, and can access the related value directly.
Example Resulting Dictionary/Array:
[Name][Value1][Value2]
[Actinobacter][GATCGA...TCA][8924342]
[XYZbacter][BCABCA...ABC][43594344]
...
Here is my code for doing intersections, unions, differences, and other set operations on dictionaries:
class DictDiffer(object):
"""
Calculate the difference between two dictionaries as:
(1) items added
(2) items removed
(3) keys same in both but changed values
(4) keys same in both and unchanged values
"""
def __init__(self, current_dict, past_dict):
self.current_dict, self.past_dict = current_dict, past_dict
self.set_current, self.set_past = set(current_dict.keys()), set(past_dict.keys())
self.intersect = self.set_current.intersection(self.set_past)
def added(self):
return self.set_current - self.intersect
def removed(self):
return self.set_past - self.intersect
def changed(self):
return set(o for o in self.intersect if self.past_dict[o] != self.current_dict[o])
def unchanged(self):
return set(o for o in self.intersect if self.past_dict[o] == self.current_dict[o])
if __name__ == '__main__':
import unittest
class TestDictDifferNoChanged(unittest.TestCase):
def setUp(self):
self.past = dict((k, 2*k) for k in range(5))
self.current = dict((k, 2*k) for k in range(3,8))
self.d = DictDiffer(self.current, self.past)
def testAdded(self):
self.assertEqual(self.d.added(), set((5,6,7)))
def testRemoved(self):
self.assertEqual(self.d.removed(), set((0,1,2)))
def testChanged(self):
self.assertEqual(self.d.changed(), set())
def testUnchanged(self):
self.assertEqual(self.d.unchanged(), set((3,4)))
class TestDictDifferNoCUnchanged(unittest.TestCase):
def setUp(self):
self.past = dict((k, 2*k) for k in range(5))
self.current = dict((k, 2*k+1) for k in range(3,8))
self.d = DictDiffer(self.current, self.past)
def testAdded(self):
self.assertEqual(self.d.added(), set((5,6,7)))
def testRemoved(self):
self.assertEqual(self.d.removed(), set((0,1,2)))
def testChanged(self):
self.assertEqual(self.d.changed(), set((3,4)))
def testUnchanged(self):
self.assertEqual(self.d.unchanged(), set())
unittest.main()
def combine_two_json(json_request, json_request2):
intersect = {}
for item in json_request.keys():
if item in json_request2.keys():
intersect[item]=json_request2.get(item)
return intersect

Categories

Resources