2

I have this code:

const getObject = (container, id, callback) => {
    _.each(container, (item) => {
        if (item.id === id) callback(item);
        if (item.files) getObject(item.files, id, callback);
    });
}

that will get me the object inside an object such as this:

const structure = {
    id: 1,
    name: "Struct",
    files: [
        {
            id: 2,
            type: "folder",
            name: "assets",
            files: [
                {
                    id: 3,
                    type: "folder",
                    name: "important",
                    files: [
                        {
                            id: 4,
                            type: "folder",
                            name: "modules",
                            files: [
                                {
                                    id: 5,
                                    type: "folder",
                                    name: "foo",
                                    files: [
                                        {
                                            type: "file",
                                            name: "foo.js"
                                        }

                                    ]
                                },
                                {
                                    id: 6,
                                    type: "folder",
                                    name: "bar",
                                    files: [
                                        {
                                            type: "file",
                                            name: "bar.js"
                                        }

                                    ]
                                }
                            ]
                        }

                    ]
                }
            ]
        }
    ]
}

Example:

getObject(structure.files, 6, (target) => {
    console.log(target)
})  // returns { "id": 6, "type": "folder", "name": "items", "files": [ { "type": "file", "name": "bar.json" } ] }

My problem is that I need to get the "path" back to the initial element (structure.files). What is the best way to go around this?

For example in this situation, it would return [1,2,3,4,6].

0

3 Answers 3

1

You could use the classic function and this argument for the path in the callback for Array#some. Return full path when the target is found.

var structure = { id: 1, name: "Struct", files: [{ id: 2, type: "folder", name: "assets", files: [{ id: 3, type: "folder", name: "important", files: [{ id: 4, type: "folder", name: "modules", files: [{ id: 5, type: "folder", name: "foo", files: [{ type: "file", name: "foo.js" }] }, { id: 6, type: "folder", name: "bar", files: [{ type: "file", name: "bar.js" }] }] }] }] }] },
    path;

[structure].some(function iter(a) {
    if (a.id === 6) {
        path = this.concat(a.id);
        return true;
    }
    return Array.isArray(a.files) && a.files.some(iter, this.concat(a.id));
}, []);

console.log(path);

ES6 version with closure for the path collecting variable p.

var structure = { id: 1, name: "Struct", files: [{ id: 2, type: "folder", name: "assets", files: [{ id: 3, type: "folder", name: "important", files: [{ id: 4, type: "folder", name: "modules", files: [{ id: 5, type: "folder", name: "foo", files: [{ type: "file", name: "foo.js" }] }, { id: 6, type: "folder", name: "bar", files: [{ type: "file", name: "bar.js" }] }] }] }] }] },
    path,
    iter = p => a  => {
        if (a.id === 6) {
            path = p.concat(a.id);
            return true;
        }
        return Array.isArray(a.files) && a.files.some(iter(p.concat(a.id)))
    };

[structure].some(iter([]));

console.log(path);

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

Comments

0

More generic way of doing this. You don't need to check for specific id like the other answer! This will work even if you add more complex structure. Take a look.

I'm doing a recursive check and adding the id to the array which will be returned after going through all the possible paths. Hope it helps!

const structure = {"id":1,"name":"Struct","files":[{"id":2,"type":"folder","name":"assets","files":[{"id":3,"type":"folder","name":"important","files":[{"id":4,"type":"folder","name":"modules","files":[{"id":5,"type":"folder","name":"foo","files":[{"type":"file","name":"foo.js"}]},{"id":6,"type":"folder","name":"bar","files":[{"type":"file","name":"bar.js"}]}]}]}]}]}

  function getId(obj, idArray) {
    var idArr = idArray ? idArray : []
    if (obj.files) {
      obj.id && idArr.push(obj.id)
      obj.files.forEach(function(nextObj, i) {
        if (nextObj.id)
         getId(nextObj, idArr)
       })
      return idArr
    }
  }
  console.log(getId(structure))

1 Comment

you get any nodes, not the path to a specific node, as the op want.
0
const recurse = function (container, id) {
  console.log("Now on node:", container);
  if (container.id === id) {
    console.log("Found the child whose existence was foretold!", container);
    var path = [];
    path.unshift(container.id);
    return path;
  } else {
    console.log("Your princess is in another castle", container);
    if (container.files && container.files.length > -1) {
      for(let i = 0; i < container.files.length; i++) {
        var child = container.files[i];
        var possiblePath = recurse(child, id);
        if (possiblePath) {
          possiblePath.unshift(container.id);
          console.log("This is " + container.id + " reporting in, we have the child.", possiblePath);
          return possiblePath;
        }
      }
    } else {
      return null;
    }
  }
}

const getObject = function(container, id, callback) {
  console.log("Starting recursion, looking for id", id);
  var path = recurse(container, id);
  if (path && path.length > 0) {
    console.log("Path to target element found", path);
  } else {
    console.log("Target element not found.");
  }
  callback(path);
}

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.