我有一个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。
答案 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
方法get
和set
一起使用。
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
检查。一些好的读取是here和here所以我们必须添加这个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 }