Xander
Xander

Reputation: 412

Creating a new array from the parents of array child element

I have the following array

{
  "id": "111",
  "name": "1111",
  "children": [
    {
      "id": "22222",
      "name": "2222",
      "children": [
        {
          "id": "AAAA",
          "name": "AAAA",
          "children": [
            {
              "id": "DDD",
              "name": "DDD"
            },
            {
              "id": "EEE",
              "name": "EEE"
            }
          ]
        },
        {
          "id": "BBBB",
          "name": "BBB",
          "children": [
            {
              "id": "FFF",
              "name": "FFF"
            },
            {
              "id": "GGG",
              "name": "GGG",
              "children": [
                {
                  "id": "7777",
                  "name": "7777"
                },
                {
                  "id": "8888",
                  "name": "8888"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

And I would like to create an array with the parents of a child by its ID.

So for example if I wanted to get the path to the child with ID "FFF", then the array would look like something like this:

["1111", "2222", "BBB", "FFF"]

How could I go about doing that?

Upvotes: 1

Views: 666

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386746

You could take an iterative and recursive approach.

function getItems({ children, ...object }, key, value) {
    var temp;
    if (object[key] === value) return [object];
    if (children) children.some(o => temp = getItems(o, key, value));
    return temp && [object, ...temp];
}

var data = { id: "111", name: "1111", children: [{ id: "22222", name: "2222", children: [{ id: "AAAA", name: "AAAA", children: [{ id: "DDD", name: "DDD" }, { id: "EEE", name: "EEE" }] }, { id: "BBBB", name: "BBB", children: [{ id: "FFF", name: "FFF" }, { id: "GGG", name: "GGG", children: [{ id: "7777", name: "7777" }, { id: "8888", name: "8888" }] }] }] }] };

console.log(getItems(data, 'id', 'FFF'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 4

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48693

You could implement a recursive search to find all paths and return the correct one when you reach the desired name-value pair.

const isObject = (obj) => obj === Object(obj);

let data = loadData();
let expected = [ '1111', '2222', 'BBB', 'FFF' ];
let actual = findPath(data, 'name', 'FFF');

console.log(JSON.stringify(expected) === JSON.stringify(actual));

function findPath(data, key, value, includeIndicies=false) {
  let opts = { found : null, includeIndicies : includeIndicies };
  findPathInternal(data, key, value, opts, []);
  return opts.found;
}

function findPathInternal(node, key, val, opts, path) {
  if (Array.isArray(node)) {
    for (let i = 0; i < node.length; i++) {
      findPathInternal(node[i], key, val, opts, opts.includeIndicies ? path.concat(i) : path);
    }
  } else if (isObject(node)) {
    if (node[key] === val) {
      opts.found = path.concat(val); return; // Exit
    } else {
      let keys = Object.keys(node);
      for (let i = 0; i < keys.length; i++) {
        findPathInternal(node[keys[i]], key, val, opts, path.concat(node[key]));
      }
    }
  }
};

function loadData() {
  return {
    "id": "111",
    "name": "1111",
    "children": [{
      "id": "22222",
      "name": "2222",
      "children": [{
          "id": "AAAA",
          "name": "AAAA",
          "children": [{
              "id": "DDD",
              "name": "DDD"
            },
            {
              "id": "EEE",
              "name": "EEE"
            }
          ]
        },
        {
          "id": "BBBB",
          "name": "BBB",
          "children": [{
              "id": "FFF",
              "name": "FFF"
            },
            {
              "id": "GGG",
              "name": "GGG",
              "children": [{
                  "id": "7777",
                  "name": "7777"
                },
                {
                  "id": "8888",
                  "name": "8888"
                }
              ]
            }
          ]
        }
      ]
    }]
  };
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

Upvotes: -1

Related Questions