A uniqueness check in which False!= 0
You need to check JSON
for uniqueness. The validation conditions assume that the collection [false, 0]
is unique, that is, the logical type is not equal to a number.
How do I make such a check on Python
if its boolean type is a subclass of int
and is equal to numbers 1
/0
?
Examples of unique collections:
[1, True]
[[1], [True]]
[[[1], "foo"], [[True], "foo"]]
[{"foo": {"bar": [1]}}, {"foo": {"bar": [True]}})]
Direct comparison returns True
:
{"foo": {"bar": [1]}} == {"foo": {"bar": [True]}}) # True
I will clarify that I am mainly interested in the unfolding algorithm, which can be applied to the latest designs. The function for comparing 1
with True
is.
I think that the problem can be reduced to BFS, but everything is complicated by the fact that JSON
simultaneously contains both dictionaries and lists. I would like to find a universal and, preferably, non-recursive traversal algorithm.
2 answers
a = 0
b = False
print(a == b) # True
print(a == b and type(a) == type(b)) # False
You can compare values and types at the same time
def isUnique(a) -> bool:
items = set([])
for item in a:
items.add(str([item]))
return items.__len__() == a.__len__()
print(isUnique([1, True])) #True
print(isUnique([[1], [True]])) #True
print(isUnique([[[1], "foo"], [[True], "foo"]])) #True
print(isUnique([1,1])) # False
print(isUnique([[[True], "foo"], [["True"], "foo"]])) # True
print(isUnique([[[True], "foo"], [[True], "foo"]])) #False
Implemented it as follows:
def unbool(element, true=object(), false=object()):
"""
A hack to make True and 1 and False and 0 unique for ``uniq``.
"""
if element is True:
return true
elif element is False:
return false
return element
def unbool_nested(element):
"""
Iterative implementation of breadth-first search for nested unbooling
"""
if not isinstance(element, (list, dict)):
return unbool(element)
result = [] if isinstance(element, list) else {}
stack = [(element, result)]
while stack:
element, new = stack.pop()
items = enumerate(element) if isinstance(element, list) else element.items()
for key, item in items:
if not isinstance(item, (list, dict)):
x = unbool(item)
else:
sub = [] if isinstance(item, list) else {}
x = sub
stack.append((item, sub))
if isinstance(new, list):
new.append(x)
else:
new[key] = x
return result
def uniq(container):
"""
Check if all of a container's elements are unique.
Successively tries first to rely that the elements are hashable. If not, it goes to brute force.
"""
try:
return len(set(unbool(i) for i in container)) == len(container)
except TypeError:
seen = []
for element in container:
element = unbool_nested(element)
if element in seen:
return False
seen.append(element)
return True