Javascript 返回对象中每个深度属性的字符串路径数组
我有一个丑陋的1MB+JSON对象,它有许多深层属性,包括包含嵌套对象的嵌套数组等 我正在寻找一个函数,它可以为给定对象中的每个属性返回字符串“路径”数组Javascript 返回对象中每个深度属性的字符串路径数组,javascript,node.js,javascript-objects,Javascript,Node.js,Javascript Objects,我有一个丑陋的1MB+JSON对象,它有许多深层属性,包括包含嵌套对象的嵌套数组等 我正在寻找一个函数,它可以为给定对象中的每个属性返回字符串“路径”数组 ['obj.propA.first', 'obj.propA.second', 'obj.propB'] 到目前为止,我所有的搜索都找到了相反方向的解决方案。例如:获取路径字符串并获取属性值 我的直觉告诉我必须有一个比重新发明轮子更好的方法 提前谢谢 示例行为: var ugly = { a: 'a', b: ['b1', 'b2'
['obj.propA.first', 'obj.propA.second', 'obj.propB']
到目前为止,我所有的搜索都找到了相反方向的解决方案。例如:获取路径字符串并获取属性值
我的直觉告诉我必须有一个比重新发明轮子更好的方法
提前谢谢
示例行为:
var ugly = {
a: 'a',
b: ['b1', 'b2'],
c: {
c1: 'c1',
c2: ['c2a', 'c2b'],
c3: {
c3a: 'c3a',
c3b: [['c3b']],
},
c4: [{c4a: 'c4a'}],
}
};
getPaths = function(obj) {
???
};
getPaths(ugly) = [
'a',
'b[0]',
'b[1]',
'c.c1',
'c.c2[0]',
'c.c2[1]',
'c.c3.c3a',
'c.c3.c3b[0][0]',
'c.c4[0].c4a',
];
这种情况有点奇怪,可能暗示在体系结构级别存在问题,但要理解这些问题有时是继承的和/或不可避免的 node 4.2版本es2015中的一个非常糟糕的可变递归实现:
function isPlainishObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
function propinator (obj, _paths, _currentPath) {
_paths = _paths || [];
if (typeof obj !== 'object') {
_paths.push(_currentPath);
} else {
for (let prop in obj) {
let path;
if (isPlainishObject(obj)) {
path = _currentPath && `${_currentPath}.${prop}` || prop;
} else {
path = _currentPath && `${_currentPath}[${prop}]` || prop;
}
propinator(
obj[prop],
_paths,
path
);
}
}
return _paths;
}
测试:
let assert = require('assert');
assert.deepEqual(propinator(ugly), [
'a',
'b[0]',
'b[1]',
'c.c1',
'c.c2[0]',
'c.c2[1]',
'c.c3.c3a',
'c.c3.c3b[0][0]',
'c.c4[0].c4a',
]);
这只是简单的测试(虽然可能很差),所以意见/改进是非常受欢迎的。这种情况有点奇怪,可能暗示在体系结构级别上存在问题,但请理解这些东西有时是继承的和/或不可避免的 node 4.2版本es2015中的一个非常糟糕的可变递归实现:
function isPlainishObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
function propinator (obj, _paths, _currentPath) {
_paths = _paths || [];
if (typeof obj !== 'object') {
_paths.push(_currentPath);
} else {
for (let prop in obj) {
let path;
if (isPlainishObject(obj)) {
path = _currentPath && `${_currentPath}.${prop}` || prop;
} else {
path = _currentPath && `${_currentPath}[${prop}]` || prop;
}
propinator(
obj[prop],
_paths,
path
);
}
}
return _paths;
}
测试:
let assert = require('assert');
assert.deepEqual(propinator(ugly), [
'a',
'b[0]',
'b[1]',
'c.c1',
'c.c2[0]',
'c.c2[1]',
'c.c3.c3a',
'c.c3.c3b[0][0]',
'c.c4[0].c4a',
]);
这只是简单的测试(虽然可能很差),所以意见/改进是非常受欢迎的。这种情况有点奇怪,可能暗示在体系结构级别上存在问题,但请理解这些东西有时是继承的和/或不可避免的 node 4.2版本es2015中的一个非常糟糕的可变递归实现:
function isPlainishObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
function propinator (obj, _paths, _currentPath) {
_paths = _paths || [];
if (typeof obj !== 'object') {
_paths.push(_currentPath);
} else {
for (let prop in obj) {
let path;
if (isPlainishObject(obj)) {
path = _currentPath && `${_currentPath}.${prop}` || prop;
} else {
path = _currentPath && `${_currentPath}[${prop}]` || prop;
}
propinator(
obj[prop],
_paths,
path
);
}
}
return _paths;
}
测试:
let assert = require('assert');
assert.deepEqual(propinator(ugly), [
'a',
'b[0]',
'b[1]',
'c.c1',
'c.c2[0]',
'c.c2[1]',
'c.c3.c3a',
'c.c3.c3b[0][0]',
'c.c4[0].c4a',
]);
这只是简单的测试(虽然可能很差),所以意见/改进是非常受欢迎的。这种情况有点奇怪,可能暗示在体系结构级别上存在问题,但请理解这些东西有时是继承的和/或不可避免的 node 4.2版本es2015中的一个非常糟糕的可变递归实现:
function isPlainishObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
function propinator (obj, _paths, _currentPath) {
_paths = _paths || [];
if (typeof obj !== 'object') {
_paths.push(_currentPath);
} else {
for (let prop in obj) {
let path;
if (isPlainishObject(obj)) {
path = _currentPath && `${_currentPath}.${prop}` || prop;
} else {
path = _currentPath && `${_currentPath}[${prop}]` || prop;
}
propinator(
obj[prop],
_paths,
path
);
}
}
return _paths;
}
测试:
let assert = require('assert');
assert.deepEqual(propinator(ugly), [
'a',
'b[0]',
'b[1]',
'c.c1',
'c.c2[0]',
'c.c2[1]',
'c.c3.c3a',
'c.c3.c3b[0][0]',
'c.c4[0].c4a',
]);
这只是一个简单的测试(虽然可能很差),所以非常欢迎意见/改进。为什么需要这些路径?这似乎是一个奇怪的需要(不是说它一定是错的,只是需要一些上下文)
。在
中,在对象的实例上递归(或者对数组进行一些更具体的类型检查/etc)@NickTomlin-我有一个数据库,其中包含一些使用路径索引的属性的元数据。@PaulS.-我只是真的很惊讶,没有人为此制作lodash或下划线混音。@Peterhaneman不想打消您的用例,但我认为没有人这样做,因为这是一个非常罕见的场景。我在这个行业还相对年轻,但我从未遇到或听说过这样的存储/用例。如何解析重复路径?是否只需要每个对象的“terminal”属性?我认为提供一个示例源和结果会很有帮助。为什么需要这些路径?这似乎是一个奇怪的需要(不是说它一定是错的,只是需要一些上下文)。在
中,在对象的实例上递归(或者对数组进行一些更具体的类型检查/etc)@NickTomlin-我有一个数据库,其中包含一些使用路径索引的属性的元数据。@PaulS.-我只是真的很惊讶,没有人为此制作lodash或下划线混音。@Peterhaneman不想打消您的用例,但我认为没有人这样做,因为这是一个非常罕见的场景。我在这个行业还相对年轻,但我从未遇到或听说过这样的存储/用例。如何解析重复路径?是否只需要每个对象的“terminal”属性?我认为提供一个示例源和结果会很有帮助。为什么需要这些路径?这似乎是一个奇怪的需要(不是说它一定是错的,只是需要一些上下文)。在
中,在对象的实例上递归(或者对数组进行一些更具体的类型检查/etc)@NickTomlin-我有一个数据库,其中包含一些使用路径索引的属性的元数据。@PaulS.-我只是真的很惊讶,没有人为此制作lodash或下划线混音。@Peterhaneman不想打消您的用例,但我认为没有人这样做,因为这是一个非常罕见的场景。我在这个行业还相对年轻,但我从未遇到或听说过这样的存储/用例。如何解析重复路径?是否只需要每个对象的“terminal”属性?我认为提供一个示例源和结果会很有帮助。为什么需要这些路径?这似乎是一个奇怪的需要(不是说它一定是错的,只是需要一些上下文)。在
中,在对象的实例上递归(或者对数组进行一些更具体的类型检查/etc)@NickTomlin-我有一个数据库,其中包含一些使用路径索引的属性的元数据。@PaulS.-我只是真的很惊讶,没有人为此制作lodash或下划线混音。@Peterhaneman不想打消您的用例,但我认为没有人这样做,因为这是一个非常罕见的场景。我在这个行业还相对年轻,但我从未遇到或听说过这样的存储/用例。如何解析重复路径?是否只需要每个对象的“terminal”属性?我认为提供一个示例源和一个结果会很有帮助。我的i7 Haswell 2.3Ghz上的Node v5能够在9.792ms内完成385KB和8704条路径。在一个有90756条路径的6.5MB文件上,平均耗时115.749ms。有点慢,但幸运的是我有机会进行预处理和缓存。再次感谢。这当然是一个奇怪的用例,但是生成json文件的数据源无法访问元数据。唉,我被困住了。@Peterhaneman抓住你了,我明白了。如果您有任何性能调整,请告诉我。很高兴它成功了;)供参考