0

I have a nested dictionary,

d={
    "A":1, 
    "depth":0, 
    "chain":[
        {
            "A1":0.7, 
            "depth":1,
            "chain":[
                {
                    "A11":0.3,
                    "depth":2,
                    "key2":{"direct":{},"cumulative":{"B":0.3}}, 
                    "chain":[]
                }, 
                {
                    "A12":0.4, 
                    "depth":2,
                    "chain":[
                        {
                            "A121":0.4, 
                            "depth":3, 
                            "key2":{"direct": {}, "cumulative":{"C":0.2, "D": 0.2}}, 
                           "chain": []
                        }]}]},
        {
            "A2":0.3,
            "depth":1,
            "chain":[
                {
                    "A11":0.3, 
                    "depth":2, 
                    "key2":{"direct":{}, "cumulative":{"D":0.3}},
                    "chain":[]
                }]}]}

I want to return a list that the first key is repeated by x times. x is the number of elements under "chain". In this case, it would return:

["A", "A", "A1", "A1", "A2", "A12"]

I have tried the following

def from_nodes(d):
    from_n=[list(d.keys())[0]]*len(d["chain"])
    for x in d["chain"]:
        if x is not None:
            from_n.extend(from_nodes(x))
            return from_n

and got the error

TypeError                                 Traceback (most recent call last)
<ipython-input-196-6233463c604b>in <module>()
----> 1 from_nodes(test2)

<ipython-input-194-5b7ca4b6db75>in from_nodes(d)
  3     for x in d["chain"]:
  4         if x is not None:
----> 5             from_n.extend(from_nodes(x))
  6         return from_n

<ipython-input-194-5b7ca4b6db75> in from_nodes(d)
  3     for x in d["chain"]:
  4         if x is not None:
----> 5             from_n.extend(from_nodes(x))
  6         return from_n
7
  • 2
    What does your function return when all x in d["chain"] are None? Commented Jun 21, 2018 at 15:31
  • Please include the full traceback of the error. Commented Jun 21, 2018 at 15:31
  • 2
    If d["chain"] does not have anything to iterate, you never get into your for loop. Thus the function will return None You probably need to un-indent the return from_n line two times. Commented Jun 21, 2018 at 15:32
  • got the error TypeError: 'NoneType' object is not iterable Edit your question to include the full error traceback. You're making us guess where the error is happening. Commented Jun 21, 2018 at 15:32
  • @DyZ if x are None, it doesn't extend the list with anything. Commented Jun 21, 2018 at 15:36

1 Answer 1

1

As I mentioned in the comments, your error is that the return statement is indented incorrectly. If d["chain"] is empty or None, your function will return None implicitly.

Changing your function to the following:

def from_nodes(d):
    from_n=[list(d.keys())[0]]*len(d["chain"])
    for x in d["chain"]:
        if x is not None:
            from_n.extend(from_nodes(x))
    return from_n

will fix the error and the result on my computer is:

print(from_nodes(d))
#['A', 'A', 'A1', 'A1', 'depth', 'depth']

Which doesn't match your desired output-- this is because you aren't guaranteed to get a deterministic order when you call .keys().

One way to modify your function for the desired output would be to create a list of keys to ignore:

def from_nodes(d):
    ignore_keys = {"chain", "depth", "key2"}
    from_n=[list(k for k in d.keys() if k not in ignore_keys)[0]]*len(d["chain"])
    for x in d["chain"]:
        if x is not None:
            from_n.extend(from_nodes(x))
    return from_n

print(from_nodes(d))
#['A', 'A', 'A1', 'A1', 'A12', 'A2']

However, this is just me speculating what your requirements are. You need to define the correct condition for what you mean by the "first" key.

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

2 Comments

['A', 'A', 'A1', 'A1', 'A12', 'A2'] is indeed my desired output, but the first solution you provided worked perfectly on my computer, without having a list of keys to ignore
What version of python? After 3.6, dictionaries maintain insertion order.

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.