如何从key和value获取javascript对象的路径

时间:2014-08-20 11:41:42

标签: javascript object

我有一个javascript对象宽度深度。

我需要知道对象ex中这个键的确切路径:“obj1.obj2.data1”

我已经知道密钥是data1,值是123。

我的javascript对象看起来像这样

{
    obj1: {
        obj2: {
            data1: 213,
            data2: "1231",
            obj3: {
                data: "milf"
            }
        }
    },
    obj4: {
        description: "toto"
    }
}

我怎么能实现这个目标?

这是一个jsfiddle:http://jsfiddle.net/3hvav8xf/8/ 我正在尝试实现getPath。

8 个答案:

答案 0 :(得分:6)

我认为递归函数可以帮到你(更新版本,检查值)

function path(c, name, v, currentPath, t){
    var currentPath = currentPath || "root";

    for(var i in c){
      if(i == name && c[i] == v){
        t = currentPath;
      }
      else if(typeof c[i] == "object"){
        return path(c[i], name, v, currentPath + "." + i);
      }
    }

    return t + "." + name;
};

path({1: 2, s: 5, 2: {3: {2: {s: 1, p: 2}}}}, "s", 1)

答案 1 :(得分:2)

你走了!

function getPath(obj, value, path) {

    if(typeof obj !== 'object') {
        return;
    }

    for(var key in obj) {
        if(obj.hasOwnProperty(key)) {
            console.log(key);
            var t = path;
            var v = obj[key];
            if(!path) {
                path = key;
            }
            else {
                path = path + '.' + key;
            }
            if(v === value) {
                return path;
            }
            else if(typeof v !== 'object'){
                path = t;
            }
            var res = getPath(v, value, path);
            if(res) {
                return res;
            } 
        }
    }

}

getPath(yourObject, valueYouWantToFindPath);

如果找到Rerutns路径,则返回undefined。 我只用物体和它测试过它比较非常严格(即:使用===)。

<强>更新 将密钥作为参数的更新版本。

function getPath(obj, key, value, path) {

    if(typeof obj !== 'object') {
        return;
    }

    for(var k in obj) {
        if(obj.hasOwnProperty(k)) {
            console.log(k);
            var t = path;
            var v = obj[k];
            if(!path) {
                path = k;
            }
            else {
                path = path + '.' + k;
            }
            if(v === value) {
                if(key === k) {
                    return path;
                }
                else {
                    path = t;
                }
            }
            else if(typeof v !== 'object'){
                path = t;
            }
            var res = getPath(v, key, value, path);
            if(res) {
                return res;
            } 
        }
    }

}

getPath(yourObject, key, valueYouWantToFindPath);

答案 2 :(得分:1)

以下内容可在任何级别的嵌套对象中找到路径。也可以使用数组。 它返回找到的所有路径,如果您具有相同名称的键,这就是您想要的。

我喜欢这种方法,因为它可以与lodash方法getset一起使用。

function findPathsToKey(options) {
  let results = [];

  (function findKey({
    key,
    obj,
    pathToKey,
  }) {
    const oldPath = `${pathToKey ? pathToKey + "." : ""}`;
    if (obj.hasOwnProperty(key)) {
      results.push(`${oldPath}${key}`);
      return;
    }

    if (obj !== null && typeof obj === "object" && !Array.isArray(obj)) {
      for (const k in obj) {
        if (obj.hasOwnProperty(k)) {
          if (Array.isArray(obj[k])) {
            for (let j = 0; j < obj[k].length; j++) {
              findKey({
                obj: obj[k][j],
                key,
                pathToKey: `${oldPath}${k}[${j}]`,
              });
            }
          }

          if (obj[k] !== null && typeof obj[k] === "object") {
            findKey({
              obj: obj[k],
              key,
              pathToKey: `${oldPath}${k}`,
            });
          }
        }
      }
    }
  })(options);

  return results;
}

findPathsToKey({ obj: objWithDuplicates, key: "d" })
// ["parentKey.arr[0].c.d", "parentKey.arr[1].c.d", "parentKey.arr[2].c.d"]

在这里尝试-https://jsfiddle.net/spuhb8v7/1/

如果希望结果是单个键(第一次遇到),则可以将results更改为字符串,如果已定义,则返回该函数。

答案 3 :(得分:0)

JSON对象可以在JavaScript中作为关联数组处理。

因此,你可以在一些变量中循环并存储“父母”的索引。

假设整个对象存储在名为obj。

的变量中
  

for(var p1 in obj)

     

{

   for( var p2 in obj[ p1 ] )
   {
       for( var p3 in obj[ p1 ][ p2 ] )
       {
           // obj[ p1 ][ p2 ][ p3 ] is current node
           // so for Your example it is obj.obj1.obj2.data1
       }
   }
     

}

希望答案很有帮助。

答案 4 :(得分:0)

我会按照以下方式完成这项工作;

Object.prototype.paths = function(root = [], result = {}) {
  var ok = Object.keys(this);
  return ok.reduce((res,key) => { var path = root.concat(key);
                                  typeof this[key] === "object" &&
                                         this[key] !== null ? this[key].paths(path,res)
                                                            : res[this[key]] == 0 || res[this[key]] ? res[this[key]].push(path)
                                                                                                    : res[this[key]] = [path];
                                  return res;
                                },result);
};

var myObj = {
    obj1: {
        obj2: {
            data1: 213,
            data2: "1231",
            obj3: {
                data: "milf"
            }
        }
    },
    obj4: {
        description: "toto",
        cougars: "Jodi",
        category: "milf"
    }
},
value = "milf",
milfPath = myObj.paths()[value]; // the value can be set dynamically and if exists it's path will be listed.
console.log(milfPath);

几句警告:我们在使用Object原型时应该谨慎。我们的修改应该有描述符enumerable = false或者它将在for in循环中列出,例如jQuery将不起作用。 (这是jQuery的愚蠢,因为显然他们没有在for循环中进行hasOwnProperty检查。一些好的读取是herehere所以我们必须添加这个Object方法使用Object.defineProperty()将其设为enumerable = false;。但为了简单起见并留在问题的范围内,我没有在代码中包含该部分。

答案 5 :(得分:0)

我最终得到了以下功能,该功能可用于嵌套对象/数组:

function findPath (obj, name, val, currentPath) {
  currentPath = currentPath || ''

  let matchingPath

  if (!obj || typeof obj !== 'object') return

  if (obj[name] === val) return `${currentPath}['${name}']`

  for (const key of Object.keys(obj)) {
    if (key === name && obj[key] === val) {
      matchingPath = currentPath
    } else {
      matchingPath = findPath(obj[key], name, val, `${currentPath}['${key}']`)
    }

    if (matchingPath) break
  }

  return matchingPath
}

const treeData = [{
  id: 1,
  children: [{
    id: 2
  }]
}, {
  id: 3,
  children: [{
    id: 4,
    children: [{
      id: 5
    }]
  }]
}]

console.log(findPath (treeData, 'id', 5))

答案 6 :(得分:0)

这是我编写的一个非常简短且相对容易理解的函数,用于检索对象上每个属性/字段的 JSON 路径(无论嵌套有多深)。

getPaths(object) 函数只接受您想要 JSON 路径的对象并返回路径数组。或者,如果您希望用不同于标准 JSON 路径符号 $ 的符号来表示初始对象,您可以调用 getPaths(object, path),并且每个 JSON 路径将以指定的路径开始。

例如:getPaths({prop: "string"}, 'obj'); 将返回以下 JSON 路径:obj.prop,而不是 $.prop

有关 getPaths 返回的内容及其使用方式的更详细、深入的示例,请参见下文。

object = {
  "firstName": "John",
  "lastName": "doe",
  "age": 26,
  "fakeData": true,
  "address": {
    "streetAddress": "fake street",
    "city": "fake city",
    "postalCode": "12345"
  },
  "phoneNumbers": [{
    "type": "iPhone",
    "number": "0123-4567-8888"
  }, {
    "type": "home",
    "number": "0123-4567-8910"
  }]
};

function getPaths(object, path = "$") {
  return Object.entries(object).flatMap(function(o, i) {
    if (typeof o[1] === "object" && !o[1].length) {
      return `${getPaths(o[1], path + '.' + o[0])}`.split(',');
    } else if (typeof o[1] === "object" && o[1].length) {
      return Object.entries(o[1]).flatMap((no, i) => getPaths(no[1], `${path}.${o[0]}[${i}]`));
    } else {
      return `${path}.${o[0]}`;
    }
  });
}
console.log(`%o`, getPaths(object));

答案 7 :(得分:-2)

我强烈建议您使用lodash解决此问题。

在他们的文档this should help you out

// using "_.where" callback shorthand
_.find(characters, { 'age': 1 });
// →  { 'name': 'pebbles', 'age': 1, 'blocked': false }