Remove the key value pairs based on value - python

a:{
b:{cd:"abc",
de:"rty"
},
c:{cd:"abc",
de:"uuy"
},
d:{cd:"ap",
de:"uy"
}
}
I want to print values of cd and de from this dictionary and if the value of cd is same then I only want to print once.
Expected output: b abc rty
d ap uy
How can I check if the value of cd is repeated or not ?
Edit :
hash_set=set()
hash_item=v1.get('query_hash',{}).get('sha256', "")
if hash_item in hash_set:
break
else:
hash_set.add(hash_item)
This is not working

How can I check if the value of cd is repeated or not ?
If you are iterating over stuff and you don't want to process duplicates keep a container of things you have already seen and skip items if they have been seen. sets are excellent containers for membership testing as the look-up is O(1) and sets don't allow duplicates.
Here is a toy example.
stuff = 'anjdusttnnssajd'
seen = set()
for thing in stuff:
if thing in seen:
continue
print(thing.upper()) # process thing
seen.add(thing)
Or you could just make a set of the things to process then process the things in the set.
stuff = set(stuff)
for thing in stuff:
print(thing.upper())
Using your criteria.
d = {'a':{'b':{'cd':"abc",'de':"rty"},
'c':{'cd':"abc",'de':"uuy"},
'd':{'cd':"ap",'de':"uy"}}}
seen = set()
for key,thing in d['a'].items():
cd,de = thing['cd'],thing['de']
if cd in seen:
continue
else:
print(key, cd, de)
seen.add(cd)

This code should help, I formated your JSON a little bit for it to be a valid python string but you should be able to modify it as you wish
def getKeys(dict):
return [*dict]
a = {
'b':{'cd':"abc",
'de':"rty"
},
'c':{'cd':"abc",
'de':"uuy"
},
'd':{'cd':"ap",
'de':"uy"
}
}
cd_list = []
keys = getKeys(a)
for key in keys:
found = False
for checked in cd_list:
if a[key]['cd']==checked:
found = True
break
if not found:
print( f'{key} : {a[key]["cd"]} {a[key]["de"]}')
cd_list.append(a[key]['cd'])

you can try this
dict={'a':{
'b':{'cd':"abc",
'de':"rty"
},
'c':{'cd':"abc",
'de':"uuy"
},
'd':{'cd':"ap",
'de':"uy"
}
}}
count=0
for key,item in dict.items():
for key,i in item.items():
if item['b']['cd']==i['cd']:
count=count+1
lis=i['cd']
else:
print(i['cd'])
if(count>1):
print(lis)

here is your code
data = {"a":{"b":{"cd":"abc","de":"rty"},"c":{"cd":"abc","de":"uuy"},"d":{"cd":"ap","de":"uy"}}}
output = set()
for key,val in data.items():
for key1,val1 in val.items():
for key2, val2 in val1.items():
if val2 not in output:
output.add(key1)
output.add(val2)
else:
break
print(output)

Related

Recursive search JSON/DICT in Python 3

I am realizing in Python 3 some APIs that allow me to receive information about a school based on the class code. But I would like to know how I get the information through the class code.
Example:
I enter the code GF528S and I want the program to tell me the class (3C INF), the address (Address 1, Milan), and if possible also the name of the school (Test School 1) and the previous keys. Thanks in advance! Of course I use a JSON structure:
{
"schools": {
"Lombardia": {
"Milano": {
"Milano": {
"Test School 1": {
"sedi": {
"0": {
"indirizzo": "Address 1, Milan",
"classi": {
"INFORMATICA E TELECOMUNICAZIONI": {
"3C INF": "GF528S"
}
}
},
"1": {
"indirizzo": "Address 2, Milan",
"classi": {
"INFORMATICA E TELECOMUNICAZIONI": {
"1A IT": "HKPV5P",
"2A IT": "QL3J3K",
"3A INF": "X4E35C",
"3A TEL": "ZAA7LC"
}
}
}
}
}
}
}
}
}
}
When I get the values ​​from my database they are converted to a python dictionary if it helps!
After a series of tests thanks to your answers, I found that the for in .items() is blocked when it shows the indirizzo field:
In particular, it cannot search in these dictionaries:
{'classi': {'INFORMATICA E TELECOMUNICAZIONI': {'3C INF': 'GF528S'}}, 'indirizzo': 'Address 1, Milan'}
{'classi': {'INFORMATICA E TELECOMUNICAZIONI': {'1A IT': 'HKPV5P', '2A IT': 'QL3J3K', '3A INF': 'X4E35C', '3A TEL': 'ZAA7LC'}}, 'indirizzo': 'Address 2, Milan'}
I think the problem is precisely the indirizzo field. If you want to do the for first, it can be saved in a variable and deleted from the json:
del val ["address"]
The problem is that then I can't associate the address with the class.
Code:
def dictionary_check(input):
indirizzo = ""
for key,value in input.items():
if isinstance(value, dict):
dictionary_check(value)
else:
for i in value:
indirizzo += i["indirizzo"]
del i['indirizzo']
for x, y in i.items():
for z, j in y.items():
for a in j.items():
if a[1] == "HKPV5P":
print(indirizzo)
print("Classe: " + a[0])
While I can't write the exact code for you, I think it's reasonable to be able to give you a rough idea of what the code would look like, and some guidance.
I don't exactly know where this JSON data is being obtained. So it may have more / less keys when your applications runs. However, assuming the json is exactly as is, and the json data is loaded onto the variable (let's say json_map), then accessing a specific value looks something like:
json_map[key_value]
So you would want to do something similar to
json_map['schools']['Lombardia']['Milano']
and more keys until you reach the dictionary you want to play around with.
I think the point you might be confused is - if you have multiple values (that you may not be aware of what they might look like) how you handle it. For example, I think the key "sedi" (which I assume means locations) might return multiple locations (i.e. schools) and you won't know what their keys / values are. In that case, you may wish to iterate through that dictionary via something like:
for key, value in dict_.items():
# do your action
it is likely that key will be an integer (in string format) and value will be another dictionary. You will want to check a specific attribute of the dictionary to see if it's the one you're looking for.
Also, finally, when you get to the 'INFORMATICA E TELECOMUNICAZIONI' dictionary of the location(s), you may wish to return the key of the item that has the corresponding value. Something like:
for key, value in dict_.items():
if value == 'GF528S':
return key
Of course, you'll be able to replace this value of 'GF528S' to a variable so you can change it each time.
I think this is as far as I can help you without actually implementing this. I gave the benefit of the doubt that you are like me when I just started programming and I just needed someone to give me a rough outline of what to do. Any more help, I think you may need grab someone who has knowledge of what to do IRL or hire a tutor/teacher to teach you basic concepts of Programming.
search_key = "GF528S"
def recursive_search(dct,keys):
for key,value in dct.items():
if key == search_key:
print(keys,value)
if type(value) == dict:
recursive_search(value,[*keys,key])
recursive_search(dinput_dict,[])
You should use recursive function to find key or value.
def search_key(data, key, path=""):
if type(data) is dict:
for k, v in data.items():
path="{0} -> {1}".format(path, k)
if k == key or v == key:
return (k, v, path)
res = search_key(data[k], key, path)
if res is not None:
return res
result = search_key(your_dictionary, key="GF528S")
if result is not None:
print("key:", result[0])
print("value:", result[1])
print("path:", result[2])
else:
print("key or value not found!")
If you want to search entire of dictionary and get all duplicate keys or values using given pattern key, this below function is useful.
def entire_search_key(data, key, founds=[], path=""):
if type(data) is dict:
for k, v in data.items():
path="{0} -> {1}".format(path, k)
if k == key or v == key:
founds.append((k, v, path))
entire_search_key(data[k], key, founds, path)
return founds
result = entire_search_key(your_dictionary, key="ddd")
if result == []:
print("key or value not found!")
else:
for i in result:
print(i)

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")

Best way to write for loop while being able to access items in container Python

This is relatively straightforward but more pointed question on how to write the most concise if/any/for loop that accomplishes what I need. I'm rather new to Python, and much more used to the C++ way of doing things.
I need to do something like the following:
for item in my_dict:
if some_var == item.some_attribute:
if item.another_attribute exists:
variable = "A"
else variable = "B"
print "Duplicate item exists in my list of type: {}".format(variable)
I've condensed it into something like this:
if any(some_var == item.some_attribute for item in my_dict):
variable = "A" if item.another_attribute else "B"
print "Duplicate item exists in my list of type: {}".format(variable)
However, when doing this, I'm getting an "unresolved reference" error for item. Any ideas as to how I can write a concise loop, equivalence check, and presence check like I've described above in a way that allows me to access and perform methods on item?
Thank you!
EDIT: thank you so much for the answer #pjhaugh, that's exactly what I was looking for. Works beautifully! Thank you everyone for your helpful comments as well.
What's happening here is that item does not leak out of the generator expression scope (this is a good thing). You could obtain item by getting the next thing yielded by a generator, or catching that generator yielding nothing.
try:
item = next(item for item in my_dict if some_var == item.some_attribute)
variable = "A" if item.another_attribute else "B"
except StopIteration:
# there is no such item in my_dict
You can extract the objects yielded by an iterator in a for loop like this
for item in (i for i in my_dict if some_var == item.some_attribute):
variable = "A" if item.another_attribute is not None else "B"
print("Duplicate item exists in my list of type: {}".format(variable))
break
else: # no break encountered
... # not found
Currently you're iterating over the keys of the dictionary. If you want the items (pairs in c++ lingo), you need my_dict.items().
As pointed out in my comment - the any(some_var == item.some_attribute for item in my_dict) builds its own local scope. You cannot use item outside of it.
You can however loop over your dict like so:
Create minimal verifyable complete example data:
class K:
def __init__(self):
self.some_attribute = None
self.another_attribute = None
def __repr__(self):
return "{} - {}".format(self.some_attribute,self.another_attribute)
def __str__(self):
return "{} - {}".format(self.some_attribute,self.another_attribute)
k1 = K()
k1.some_attribute = 99
k2 = K()
k2.some_attribute = 33
k3 = K()
k3.some_attribute = 33
k3.another_attribute = 1
my_dict = { 1: k1, 2:k2, 3:k3}
some_var = 33
You can use a for loop like so:
variable = None
for item in my_dict.items():
k,v = item
if v.some_attribute != some_var:
print "No dupe: {}".format(v)
continue
if v.some_attribute == some_var and v.another_attribute is not None:
variable = "A"
else:
variable = "B"
print "Duplicate item exists in my list of type: {}".format(variable)
print v
Output:
No dupe: 99 - None
Duplicate item exists in my list of type: B
33 - None
Duplicate item exists in my list of type: A
33 - 1

Test if dictionary key exists, is not None and isn't blank

I have code that works but I'm wondering if there is a more pythonic way to do this. I have a dictionary and I want to see if:
a key exists
that value isn't None (NULL from SQL in this case)
that value isn't simply quote quote (blank?)
that value doesn't solely consist of spaces
So in my code the keys of "a", "b", and "c" would succeed, which is correct.
import re
mydict = {
"a":"alpha",
"b":0,
"c":False,
"d":None,
"e":"",
"g":" ",
}
#a,b,c should succeed
for k in mydict.keys():
if k in mydict and mydict[k] is not None and not re.search("^\s*$", str(mydict[k])):
print(k)
else:
print("I am incomplete and sad")
What I have above works, but that seems like an awfully long set of conditions. Maybe this simply is the right solution but I'm wondering if there is a more pythonic "exists and has stuff" or better way to do this?
UPDATE
Thank you all for wonderful answers and thoughtful comments. With some of the points and tips, I've updated the question a little bit as there some conditions I didn't have which should also succeed. I have also changed the example to a loop (just easier to test right?).
Try to fetch the value and store it in a variable, then use object "truthyness" to go further on with the value
v = mydict.get("a")
if v and v.strip():
if "a" is not in the dict, get returns None and fails the first condition
if "a" is in the dict but yields None or empty string, test fails, if "a" yields a blank string, strip() returns falsy string and it fails too.
let's test this:
for k in "abcde":
v = mydict.get(k)
if v and v.strip():
print(k,"I am here and have stuff")
else:
print(k,"I am incomplete and sad")
results:
a I am here and have stuff
b I am incomplete and sad # key isn't in dict
c I am incomplete and sad # c is None
d I am incomplete and sad # d is empty string
e I am incomplete and sad # e is only blanks
if your values can contain False, 0 or other "falsy" non-strings, you'll have to test for string, in that case replace:
if v and v.strip():
by
if v is not None and (not isinstance(v,str) or v.strip()):
so condition matches if not None and either not a string (everything matches) or if a string, the string isn't blank.
The get method for checking if a key exists is more efficient that iterating through the keys. It checks to see if the key exists without iteration using an O(1) complexity as apposed to O(n). My preferred method would look something like this:
if mydict.get("a") is not None and str(mydict.get("a")).replace(" ", "") != '':
# Do some work
You can use a list comprehension with str.strip to account for whitespace in strings.
Using if v is natural in Python to cover False-like objects, e.g. None, False, 0, etc. So note this only works if 0 is not an acceptable value.
res = [k for k, v in mydict.items() if (v.strip() if isinstance(v, str) else v)]
['a']
Here's a simple one-liner to check:
The key exists
The key is not None
The key is not ""
bool(myDict.get("some_key"))
As for checking if the value contains only spaces, you would need to be more careful as None doesn't have a strip() method.
Something like this as an example:
try:
exists = bool(myDict.get('some_key').strip())
except AttributeError:
exists = False
Well I have 2 suggestions to offer you, especially if your main issue is the length of the conditions.
The first one is for the check if the key is in the dict. You don't need to use "a" in mydict.keys() you can just use "a" in mydict.
The second suggestion to make the condition smaller is to break down into smaller conditions stored as booleans, and check these in your final condition:
import re
mydict = {
"a":"alpha",
"c":None,
"d":"",
"e":" ",
}
inKeys = True if "a" in mydict else False
isNotNone = True if mydict["a"] is not None else False
isValidKey = True if not re.search("^\s*$", mydict["a"]) else False
if inKeys and isNotNone and isValidKey:
print("I am here and have stuff")
else:
print("I am incomplete and sad")
it check exactly for NoneType not only None
from types import NoneType # dont forget to import this
mydict = {
"a":"alpha",
"b":0,
"c":False,
"d":None,
"e":"",
"g":" ",
}
#a,b,c should succeed
for k in mydict:
if type(mydict[k]) != NoneType:
if type(mydict[k]) != str or type(mydict[k]) == str and mydict[k].strip():
print(k)
else:
print("I am incomplete and sad")
else:
print("I am incomplete and sad")
cond is a generator function responsible for generating conditions to apply in a short-circuiting manner using the all function. Given d = cond(), next(d) will check if a exists in the dict, and so on until there is no condition to apply, in that case all(d) will evaluate to True.
mydict = {
"a":"alpha",
"c":None,
"d":"",
"e":" ",
}
def cond ():
yield 'a' in mydict
yield mydict ['a']
yield mydict ['a'].strip ()
if all (cond ()):
print("I am here and have stuff")
else:
print("I am incomplete and sad")

How to make my code more simple using python

this is my code:
def set_floor_point(self,floor_point=None):
if self.data.get('stage'):
self.data['stage'] = {}
stage_number = self.get_stage_number()
floor_number = self.get_floor_number()
if self.data['stage'].get(stage_number):
self.data['stage'][stage_number] = {}
if self.data['stage'][stage_number].get('floor_point'):
self.data['stage'][stage_number]['floor_point'] = {}
if self.data['stage'][stage_number]['floor_point'].get(floor_number):
self.data['stage'][stage_number]['floor_point'][floor_number] = {}
self.data['stage'][stage_number]['floor_point'][floor_number] = floor_point
and the dict i create when first time is like this :
stage =
{
0:{
'floor':{
0:{
'floor_point':0,
'gift':{}
}
}
}
}
but i think my code is not very good , it is too Cumbersome,
so Are someone know more simple way ,
thanks
data = collections.defaultdict(lambda: collections.defaultdict(
lambda: collections.defaultdict(dict)))
data['stage'][3]['floor_point'][2] = 5
print data
I'm not sure what you want to achieve. A recurring theme in your code is:
if some_dict.get(key):
some_dict[key] = {}
That means: if some_dict has a key key and some_dict[key] is a truthy value, then replace some_dict[key] by {}. If some_dict doesn't have a key key or some_dict[key] is a falsy value (None, 0, False, [] etc.), then do nothing.
If that is what you wanted, you could clarify your like this:
def replace_value_by_empty_dict(d, key):
if d.get(key):
d[key] = {}
...
replace_value_by_empty_dict(self.data, 'stage')
etc.
But if that's not what you intended (the code will break if one of the ifs is true), you might want to phrase the problem in english words or pseudocode to clarify the structure of the problem.
And have a look at collections.defaultdict.

Categories

Resources