'How to get all the keys from the dictionary on JS?

OB = {
  "138": {
    "img": "album_img_608842801.png",
    "children": {
      "215": {
        "img": "album_img_386920978.png",
        "children": {
          "217": {
            "name": "Veronica Zemanova",
            "children": {
              "218": {
                "img": "album_img_884191953.png",
                "children": {
                  "226": {
                    "img": "album_img_912163411.png",
                    "children": {
                      "229": {
                        "img": "album_img_221377469.png",
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
};

Python code I was able to make

def recursive_items(dictionary):
    for key, value in dictionary.items():
        if type(value) is dict:
            yield (key, value)
            yield from recursive_items(value)
        else:
            yield (key, value)

for key in recursive_items(OB):
    print(key)

How can this code be rewritten for js? The size of the array is initially unknown We need to get the result in the form: [138,215,217,218,226,229] Thanks everyone for the replies!



Solution 1:[1]

Similar to your python solution, we will recursively traverse the object.

We test if the key is a number, and if it is, we yield it, and all of the number keys of its children.

function* defines a generator function in JavaScript.

yield yields a new value in the generator

yield* yields all the values in the iterable given. (Similar to yield from in Python, if I had to guess)

More info at https://javascript.info/generators

const OB = {
  "138": {
    "img": "album_img_608842801.png",
    "children": {
      "215": {
        "img": "album_img_386920978.png",
        "children": {
          "217": {
            "name": "Veronica Zemanova",
            "children": {
              "218": {
                "img": "album_img_884191953.png",
                "children": {
                  "226": {
                    "img": "album_img_912163411.png",
                    "children": {
                      "229": {
                        "img": "album_img_221377469.png",
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
};

// generator function, like python
function* numberKeys(obj) {
    // for each key in the object
    for (const key in obj) {
        // if the key is a number
        if (!isNaN(key)) {
            // then we yield the key
            yield key;
            
            // then we yield all the number keys of the children
            yield* numberKeys(obj[key].children);
        }
    }
}

for (const key of numberKeys(OB)) {
    console.log(key);
}

Solution 2:[2]

Here's another method that uses Object.keys to return an array of keys and Array.prototype.reduce to process it. It's a similar method to @kellys, but I don't use generators (perhaps I should) and thought I'd drop this here in case it's helpful.

function pluckNumericKeys(obj, acc = []) {
  return Object.keys(obj).reduce((acc, key) => {
    if (!isNaN(key)) acc.push(key)
    if (typeof obj[key] === 'object') acc = pluckNumericKeys(obj[key], acc)
    return acc
  }, acc)
}

const OB = {
  "138": {
    "img": "album_img_608842801.png",
    "children": {
      "215": {
        "img": "album_img_386920978.png",
        "children": {
          "217": {
            "name": "Veronica Zemanova",
            "children": {
              "218": {
                "img": "album_img_884191953.png",
                "children": {
                  "226": {
                    "img": "album_img_912163411.png",
                    "children": {
                      "229": {
                        "img": "album_img_221377469.png",
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

const result = pluckNumericKeys(OB)
console.log(result)

Solution 3:[3]

You can recursively get all the children key value using array#map and flatten the result.

const OB = { "138": { "img": "album_img_608842801.png", "children": { "215": { "img": "album_img_386920978.png", "children": { "217": { "name": "Veronica Zemanova", "children": { "218": { "img": "album_img_884191953.png", "children": { "226": { "img": "album_img_912163411.png", "children": { "229": { "img": "album_img_221377469.png", } } } } } } } } } } } };
const getKeys = o => Object.keys(o).map(k => ([k, o[k].children ? getKeys(o[k].children) : []])).flat(Infinity);
console.log(getKeys(OB));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Solution 4:[4]

A non-recursive option (in case that's useful):

const get_number_keys = (obj) => {
  let acc = [];
  let queue = [obj];
  
  while(queue.length > 0) {
    const next = queue.pop();
    acc = acc.concat( Object.keys(next).filter((key) => !isNaN(key)).map((key) => +key) );
    queue = queue.concat( Object.values(next).filter((item) => typeof item === 'object') );
  }
  
  return acc;
};

const OB = {
  "138": {
    "img": "album_img_608842801.png",
    "children": {
      "215": {
        "img": "album_img_386920978.png",
        "children": {
          "217": {
            "name": "Veronica Zemanova",
            "children": {
              "218": {
                "img": "album_img_884191953.png",
                "children": {
                  "226": {
                    "img": "album_img_912163411.png",
                    "children": {
                      "229": {
                        "img": "album_img_221377469.png",
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
};

console.log(get_number_keys(OB));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 hittingonme
Solution 2 Charlie Schliesser
Solution 3 Hassan Imam
Solution 4 Ben Stephens