Home > Blockchain >  Recursively search nested object for certain key OR value
Recursively search nested object for certain key OR value

Time:09-02

I want to use recursion to search through a nested object for a certain key OR value and then return that key AND value as an object.

However, I think I am getting the understanding of it a bit wrong, as found always returns empty {}.

Is this because it is getting overwritten? I used Googles snippets to walk through the call stack and can see that the correct key and value are being passed to found, but then it seems to get set back to {} and it continues to iterate through the other objects.

const test = [
  {
    "jack's assets": {
      car: "Mercedes",
      house: "6 bed mansion",
      laptop: "PC",
      phone: "Samsung",
      watch: "Cartier",
      trainers: "Adidas",
    },
  },
  {
    "mikes's assets": {
      car: "Audi",
      house: "4 bed detached",
      laptop: "MacBook",
      phone: "iPhone",
      watch: "Rolex",
      trainers: "Nikes",
      "wifes assets": {
        car: "Jeep",
        laptop: "Lenovo",
        phone: "Nokia",
        watch: "Rotary",
        trainers: "Kickers",
      },
    },
  },
];

function dataLayerSearch(data, input) {
  let found = {};

  for (let obj in data) {
    if (typeof data[obj] === "object") {
      dataLayerSearch(data[obj], input);
    } else {
      if (obj === input || data[obj] === input) {
        found[obj] = data[obj];
      }
    }
  }
  return found;
}

dataLayerSearch(test, "Nikes");

CodePudding user response:

I believe you are getting an empty object back because in your example, your match is >1 layer deep, and your recursive call is not setting the return value to anything, so your original found variable isn't ever being set at the top level. Something like the below would find each instance of your search term and insert that key/value as an object into an array and return the array.

const test = [{ "jack's assets": { car: "Mercedes", house: "6 bed mansion", laptop: "PC", phone: "Samsung", watch: "Cartier", trainers: "Adidas" } }, { "mikes's assets": { car: "Audi", house: "4 bed detached", laptop: "MacBook", phone: "iPhone", watch: "Rolex", trainers: "Nikes", "wifes assets": { car: "Jeep", laptop: "Lenovo", phone: "Nokia", watch: "Rotary", trainers: "Kickers" } } }];

function dataLayerSearch(data, input) {
  let found = [];
  let obj = {};

  for (let key in data) {
    if (typeof data[key] === "object") {
      found.push(...dataLayerSearch(data[key], input));
    } else {
      if (key === input || data[key] === input) {
        obj[key] = data[key]
        found.push(obj);
        obj = {}
      }
    }
  }
  return found;
}

console.log(dataLayerSearch(test, "Nikes"));
console.log(dataLayerSearch(test, "laptop"));

CodePudding user response:

You could return early on find.

BTW, naming a key as obj is misleading.

function dataLayerSearch(data, input) {
    const
        result = [],
        object = {};

    let found = false;

    for (const key in data) {
        if (data[key] === input) {
            object[key] = data[key];
            if (!found) {
                found = true;
                result.push(object);
            }
        }
        if (data[key] && typeof data[key] === "object") {
            const temp = dataLayerSearch(data[key], input);
            if (temp) result.unshift(...temp);
        }
    }
    return result.length
        ? result
        : undefined;
}

const test = [{ "jack's assets": { car: "Mercedes", house: "6 bed mansion", laptop: "PC", phone: "Samsung", watch: "Cartier", trainers: "Adidas", foo: "bar" } }, { "mikes's assets": { car: "Audi", house: "4 bed detached", laptop: "MacBook", phone: "iPhone", watch: "Rolex", trainers: "Nikes", "wifes assets": { car: "Jeep", laptop: "Lenovo", phone: "Nokia", watch: "Rotary", trainers: "Kickers", foo: "bar" }, foo: "bar" } }];

console.log(dataLayerSearch(test, "Nikes"));
console.log(dataLayerSearch(test, "bar"));

  • Related