rel*_*one 1 javascript recursion search object
我目前在json对象中进行深度搜索时遇到问题,尽管我认为这个问题一定已经解决了,但到目前为止我找不到任何真正有用的东西(而且我实际上也发现了很多东西,这个线程。也许我今天看代码已经太久了,但是并没有真正帮助我)
基本上我想要的很简单。我有一个JSON-Object,里面充满了对象。我想要的是一个函数,该函数返回包含所有包含给定键值对的所有对象的数组。我做了这个功能来返回第一个发现的对象,它工作得很好
deepSearch: function(Obj, Key, Value){
var returned = [];
var result = false;
var searchObj = function(_Obj, _Key, _Value){
if(_Obj[_Key]===_Value){
return _Obj;
} else {
return false;
}
}
result = searchObj(Obj, Key, Value);
$.each(Obj, function(key, value){
if(typeof(Obj[key]) === 'object' && Obj[key]!== null && !result)
result = customGeneralFunctions.objects.deepSearch(Obj[key], Key, Value);
if(result) return result;
});
return result;
}
Run Code Online (Sandbox Code Playgroud)
现在,我想对其进行更改,以返回包含该对所有对象的数组。我已经尝试了一段时间了,我认为这不会是一个太大的改变,但我只是无法解决这个问题。也许有人对我有帮助。预先感谢和
克里斯问候
不能让它传递带有示例的3个答案,所有这些都有缺陷。所有这些都说明了一些经典的Javascript编码-
null 是一个对象更新答案已更改。
由于代码不再可见,因此我将在迭代对象的属性时留下警告,并且您通常会typeof检查对象是否具有null类型,因此请务必检查是否有对象"object"
getObject返回到早期,并且无法找到嵌套在满足条件的对象内的其他对象。尽管通过删除返回值很容易解决,但TypeError: Cannot read property 'find' of null如果要搜索的对象中包含一个包含null的数组,它仍然会抛出a 。
for in 不加选择的迭代器更新答案已被删除。
我在下面的代码段中添加了删除的代码作为示例,该代码function deepSearch存在致命缺陷,很可能会引发RangeError: Maximum call stack size exceeded错误,然后找到您要查找的对象。例如deepSearch({ a:"a"},"id",3);。使用时for in,应键入check,因为它会迭代字符串以及对象的属性。
function deepSearch(object, key, value) {
var filtered = [];
for (var p in object)
if (p === key && object[p] === value) filtered.push(object);
else if (object[p]) filtered = filtered.concat(deepSearch(object[p], key, value));
return filtered;
}Run Code Online (Sandbox Code Playgroud)
Alex K search通过了大多数测试(在问题的合理范围内),但前提// tip: here is a good idea to check for hasOwnProperty是必须包含注释形式的代码。
但这表示该函数具有缺陷(并且效率低下),因为它将调用predicate对象的所有属性,并且我可以想到许多情况,在这些情况下,该函数可以返回对同一对象的许多引用,例如,对带有属性key不具有value predicate = (key,val)=>{return key === "id" && val !== 3}。
搜索仅应为每个对象添加一个条目,因此我们应测试对象而不是属性。我们永远不能相信回调能够完成我们期望的事情。
而且,因为这是公认的答案,所以我应该指出,Array.concat在这种情况下,实际上不应该使用它。使用闭包效率更高,并且不必将当前状态传递给每个递归。
将它们全部铺平的缺陷。
我不确定它是否相关,因为问题确实指出数据来自JSON形式,因此将没有任何循环引用(JSON无法引用)。
但我将解决该问题和几种解决方案。
循环引用只是引用自身的对象。例如。
var me = {};
me.me = me;
Run Code Online (Sandbox Code Playgroud)
如果将其作为参数传递,则会使所有其他答案崩溃。循环引用非常普遍。
一些解决方案。
第一种解决方案是仅接受JSON字符串形式的数据,并以JSON字符串形式相等地返回数据(这样就可以保持平衡,并且Universe不会爆炸)。因此消除了任何循环引用的机会。
跟踪递归深度并设置一个限制。尽管这将阻止调用栈溢出,但不会阻止结果出错,因为浅循环引用可以创建重复的对象引用。
快速而又肮脏的解决方案是一个简单的尝试,它throw TypeError("Object can not be searched");适用于JSON.stringify以及数据总线那端的那些。
最好的解决方案是回收对象。在这种情况下,这非常适合我们使用的实际算法。对于遇到的每个唯一对象,我们将其放置在数组中。如果遇到该数组中的对象,我们将忽略它并继续前进。
因此,通用的解决方案是安全的(我希望)并且是灵活的。尽管它是为ES6编写的,所以必须以babel或类似形式提供传统支持。虽然它确实带有一个但是!
var me = {};
me.me = me;
Run Code Online (Sandbox Code Playgroud)
它适用于我可以提出的所有测试用例,但这根本不是确定的测试。我将其添加到中,Object.prototype因为您不应该这样做!!!也不使用此类函数或其派生词。
这是我第一次编写这样的函数,原因是我以前从未写过类似的东西,我知道数据看起来像什么,而不必创建危险的递归迭代器来查找所需的东西。如果您正在编写代码,但不确定所使用的数据,则整个项目的设计中有问题。
| 归档时间: |
|
| 查看次数: |
1974 次 |
| 最近记录: |