深度搜索JSON对象

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)

现在,我想对其进行更改,以返回包含该对所有对象的数组。我已经尝试了一段时间了,我认为这不会是一个太大的改变,但我只是无法解决这个问题。也许有人对我有帮助。预先感谢和

克里斯问候

Bli*_*n67 5

安全的深层物体搜索?

不能让它传递带有示例的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因为您不应该这样做!!!也不使用此类函数或其派生词。

这是我第一次编写这样的函数,原因是我以前从未写过类似的东西,我知道数据看起来像什么,而不必创建危险的递归迭代器来查找所需的东西。如果您正在编写代码,但不确定所使用的数据,则整个项目的设计中有问题。