如何递归搜索对象树并使用 JavaScript/Prototype 1.7 基于键/值返回匹配的对象
Posted
技术标签:
【中文标题】如何递归搜索对象树并使用 JavaScript/Prototype 1.7 基于键/值返回匹配的对象【英文标题】:How do I recursively search an object tree and return the matching object based on a key/value using JavaScript/Prototype 1.7 【发布时间】:2011-03-26 15:52:46 【问题描述】:我有一些嵌套的对象数据,我想搜索它并根据 id 返回匹配的对象。
var data = [id: 0, name: 'Template 0', subComponents:[
id: 1, name: 'Template 1', subItems:[
id: 2, name: 'Template 2', subComponents:[id: 3, name: 'Template 3'], subItems: [id: 4, name: 'Template 4']
]
]
];
所以我想做这样的事情
getObjectByKeyValue(id: 3)
并让它返回
id: 3, name: 'Template 3'
一般来说,这是必须完成的,因为我有子项和子组件,每个子项都可以有子项。
我使用 Prototype 1.7 进行了尝试,但没有运气 - 我认为这只是搜索一个数组,而不是一个带有子节点的树:
data.find(function(s)return s.id == 4;)
提前谢谢!!!!!!
【问题讨论】:
【参考方案1】:我走了一条稍微不同的路线,将 findKey
方法设为 Object 原型:
Object.prototype.findKey = function(keyObj)
var p, key, val, tRet;
for (p in keyObj)
if (keyObj.hasOwnProperty(p))
key = p;
val = keyObj[p];
for (p in this)
if (p == key)
if (this[p] == val)
return this;
else if (this[p] instanceof Object)
if (this.hasOwnProperty(p))
tRet = this[p].findKey(keyObj);
if (tRet) return tRet;
return false;
;
您将直接在数据对象上调用它,并传入您要查找的键/值:
data.findKey( id: 3 );
请注意,此函数允许您根据任意键查找对象:
data.findKey( name: 'Template 0' );
See example →(打开控制台查看结果)
【讨论】:
我更喜欢这个解决方案,但是当原型库混合在一起时这似乎不起作用 - 任何线索如何使它与原型库一起工作? 我将 fiddle 切换为包含 Prototype 1.7 库,它仍然适用于我,所以我不确定您遇到了什么问题。 不错的解决方案。如果我想基于多个键进行搜索怎么办。为相同添加了question here 糟糕糟糕糟糕!原生对象原型的扩展! 如果你不想扩展对象原型,这很容易修改为一个独立的方法——只需传入数据以搜索并用传递的参数名称替换对它的引用。跨度> 【参考方案2】:不是最好的最终解决方案。 但可以让您开始寻找您正在寻找的东西......
var data = [id: 0, name: 'Template 0', subComponents:[
id: 1, name: 'Template 1', subItems:[
id: 2, name: 'Template 2', subComponents:[id: 3, name: 'Template 3'], subItems: [id: 4, name: 'Template 4']
]
]
];
function returnObject(data,key,parent)
for(var v in data)
var d = data[v];
if(d==key)
return parent[0];
if(d instanceof Object)
return returnObject(d,key,data);
;
function returnObjectWrapper(datavar,key)
return returnObject(datavar,key.id)
returnObjectWrapper(data,id:3)
【讨论】:
【参考方案3】:请在下方查看我的解决方案或http://jsfiddle.net/8Y6zq/:
var findByKey = function (obj, key)
var j, key = key || '', obj = obj || , keys = key.split("."),
sObj = [], ssObj = [], isSelector = !!(keys.length > 0);
var findKey = function (obj, key)
var k;
for (k in obj)
if (k === key)
sObj.push(obj[k]);
else if (typeof obj[k] == 'object')
findKey(obj[k], key);
;
if (isSelector)
var nKey = keys.shift();
findKey(obj, nKey);
while (keys.length > 0)
nKey = keys.shift();
if (sObj.length > 0)
ssObj = sObj.slice(0), sObj = [];
for (j in ssObj)
findKey(ssObj[j], nKey);
else
findKey(obj, key);
// return occurrences of key in array
return (sObj.length === 1) ? sObj.pop() : sObj;
;
var data = [
id: 0, name: 'Template 0', subComponents: [
id: 1, name: 'Template 1', subItems: [
id: 2, name: 'Template 2', subComponents: [
id: 3, name: 'Template 3'
], subItems: [
id: 4, name: 'Template 4'
]
]
],
subComponents:
comp1:'comp1 value',
comp2:'comp2 value',
];
alert(JSON.stringify(findByKey(data, 'subComponents')));
alert(JSON.stringify(findByKey(data, 'subComponents.comp1')));
alert(JSON.stringify(findByKey(data, 'subComponents.comp2')));
在这个实现中,我们可以使用 KEY 或 SELECTOR 搜索(例如"<paren_key>.<child_key_1>.<child_key_2>. ... <child_key_N>"
)
【讨论】:
【参考方案4】:如果您确实需要通过树数据搜索返回所有结果(不是唯一键),这里是 mVChr 答案的一个小修改版本:
Object.prototype.findKey = function (keyObj)
var p, key, val, tRet;
var arr = [];
for (p in keyObj)
if (keyObj.hasOwnProperty(p))
key = p;
val = keyObj[p];
for (p in this)
if (p == key)
if (this[p] == val)
arr.push(this);
else if (this[p] instanceof Object)
if (this.hasOwnProperty(p))
tRet = this[p].findKey(keyObj);
if (tRet)
for (var i = 0; i < tRet.length; i++)
arr.push(tRet[i]);
if (arr.length > 0)
return arr;
else
return false;
;
【讨论】:
【参考方案5】:我们现在使用object-scan 来完成这样的数据处理任务。一旦您了解如何使用它,它就会非常强大。以下是您回答问题的方式
// const objectScan = require('object-scan');
const find = (id, input) => objectScan(['**'],
abort: true,
rtn: 'value',
filterFn: ( value ) => value.id === id
)(input);
const data = [ id: 0, name: 'Template 0', subComponents: [ id: 1, name: 'Template 1', subItems: [ id: 2, name: 'Template 2', subComponents: [ id: 3, name: 'Template 3' ], subItems: [ id: 4, name: 'Template 4' ] ] ] ];
console.log(find(3, data));
// => id: 3, name: 'Template 3'
.as-console-wrapper max-height: 100% !important; top: 0
<script src="https://bundle.run/object-scan@13.8.0"></script>
免责声明:我是object-scan的作者
【讨论】:
以上是关于如何递归搜索对象树并使用 JavaScript/Prototype 1.7 基于键/值返回匹配的对象的主要内容,如果未能解决你的问题,请参考以下文章
sh shell函数用于爬网dns树并在每个父区域中搜索SRV记录。一旦找到第一个SRV记录,它将退出。
python 打印Linux设备树并可选择搜索该树中的字符串。需要顶级dts文件作为输入。 #linux #python
2021-06-12:已知一棵搜索二叉树上没有重复值的节点,现在有一个数组arr,是这棵搜索二叉树先序遍历的结果。请根据arr生成整棵树并返回头节点。