1

I have 3 different dictionaries in python like these

d1 = {'simple_key':'hello'}
d2 = {'k1':{'k2':'hello'}}
d3 = {'k1':[{'nest_key':['this is deep',['hello']]}]}

and I want to grab the word 'hello' from these dictionaries. But the problem I am facing is that I want to find a generic way to extract it. How can I do it?

5
  • You can't because their position is difference? You can create a function to do that, but in a single line I don't think it's possible. Commented Jan 29, 2020 at 19:40
  • What do you mean a "generic way to extract it"? Do you want a function/piece of code that tells your its 'location' (ie index in each nesting) Commented Jan 29, 2020 at 19:47
  • What do you mean by a "generic way"? In a sense, dictionary[key1][key2]...[keyN] is a generic way to get to any element. Or do you simply want to check that there is "hello" somewhere as a value? Commented Jan 29, 2020 at 19:47
  • if "hello" in json.dumps(d1)? Commented Jan 29, 2020 at 19:50
  • @Andrei exactly. I want to check that is the word 'hello' present in the values Commented Jan 29, 2020 at 20:25

3 Answers 3

3

To get the key path in the dict using value, you could flatten it as json.

>>> from json_flatten import flatten
>>> d1 = {'simple_key':'hello'}
>>> d2 = {'k1':{'k2':'hello'}}
>>> d3 = {'k1':[{'nest_key':['this is deep',['hello']]}]}
>>> flatten(d2)
{'k1.k2': 'hello'}
>>> flat = flatten(d3)
{'k1.0.nest_key.0': 'this is deep', 'k1.0.nest_key.1.0': 'hello'}

To find the matching keys, use,

>>> [k for k, v in flat.items() if v == 'hello']
['k1.0.nest_key.1.0']

JSON Flatten

Sign up to request clarification or add additional context in comments.

Comments

0

You can keep going inside the dictionary until you are at a value, not a dictionary. Recursion would be helpful here:

def get_value(dict):
     dict_value = list(dict.values())[0]
     if type(dict_value) is dict:
          get_value(dict_value)
     else: 
          return dict_value

there is probably a nicer way to do dict_value = list(dict.values())[0] but not coming to mind right now

2 Comments

This looks like it would fail on his third example.
It wouldn't fail but it doesn't make it all the way through. I ran it and got [{'nest_key': ['this is deep', ['hello']]}] If the data structure isn't consistant then I'm not sure if there is way to go all the way down
0

You could make your own flattener function which yields the values in a dict and members of a list:

def is_nonstring_iterable(x):
    return ((hasattr(x, "__iter__") or hasattr(x, "__getitem__")) 
        and not isinstance(x, str))

def flatten(thing):
    """ Recursively iterate through values in dictionary-like object or members 
        in lists, tuples or other non-string iterables """
    if hasattr(thing, "values"):
        thing = thing.values()
    if is_nonstring_iterable(thing):
        for element in thing:
            yield from flatten(element)
    else:
        yield thing

for d in [d1, d2, d3]:
    print(list(flatten(d)))
    print(any(item == "hello" for item in flatten(d))) # returns whether hello is found

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.