Reputation: 429
Let's say we have:
stack = [
{'id': '1', 'name': {'firstname': 'bob', 'lastname': 'smith'}},
{'id': '2', 'name': {'firstname': 'jane', 'lastname': 'abb'}},
{'id': '3', 'name': {'firstname': 'flo', 'lastname': 'gram', 'middle': 'remi'}},
{'id': '4', 'name': {'firstname': 'frank', 'lastname': 'glow'}, 'partner': 'diane'}
]
needles = [{'name':{'lastname': 'gram'}},
{'partner': 'diane'}
]
We'd like a function find, like so:
list = find(needles, stack)
print(list)
>[{id: '3', name: {firstname: 'flo', lastname: 'gram', middle: 'remi'}}, {id: '4', name: {firstname: 'frank', lastname: 'glow'}, partner: 'diane'}]
At first I wanted to use items(), like so:
def find(needle, stack):
result = []
for needle in needles:
for item in stack:
if needle.items() <= item.items():
result.append()
But this returns:
[{'id': '4', 'name': {'firstname': 'frank', 'lastname': 'glow'}, 'partner': 'diane'}]
Because the item match has to be exact, I would have to pass ['name': {'firstname': 'flo', 'lastname': 'gram', 'middle': 'remi'}, {'partner': 'diane'}'
for my function to return the desired result.
I am not sure where to go from here. Since my stack can be nested for an unknown depth ({a:{b:{c:value}}}) the solution might be some sort of recursion but it might not be necessary since I want to check for the exact 'path' (keys) in needle. It comes down to partially match needle items with stack items.
Upvotes: 1
Views: 55
Reputation: 71451
You can use recursion:
def find(n, s):
def exists(n, d):
if type(n) != type(d):
return False
if not isinstance(n, (dict, list)):
return n == d
if isinstance(n, list):
return any(exists(j, k) for j in n for k in d)
return all(exists(b, d.get(a, None)) for a, b in n.items())
return [i for i in s if any(exists(j, i) for j in n)]
stack = [{'id': '1', 'name': {'firstname': 'bob', 'lastname': 'smith'}}, {'id': '2', 'name': {'firstname': 'jane', 'lastname': 'abb'}}, {'id': '3', 'name': {'firstname': 'flo', 'lastname': 'gram', 'middle': 'remi'}}, {'id': '4', 'name': {'firstname': 'frank', 'lastname': 'glow'}, 'partner': 'diane'}, {'id': '5', 'name': {'firstname': ['flo', 'Flo'], 'lastname': 'gram', 'middle': 'remi'}}]
needles = [{'name': {'lastname': 'gram'}}, {'partner': 'diane'}, {'name':{'firstname':['Flo']}}]
results = find(needles, stack)
Output:
[{'id': '3', 'name': {'firstname': 'flo', 'lastname': 'gram', 'middle': 'remi'}},
{'id': '4', 'name': {'firstname': 'frank', 'lastname': 'glow'}, 'partner': 'diane'},
{'id': '5', 'name': {'firstname': ['flo', 'Flo'], 'lastname': 'gram', 'middle': 'remi'}}]
Upvotes: 1