gpt4 book ai didi

javascript - 深度搜索JSON对象

转载 作者:行者123 更新时间:2023-11-30 07:55:03 24 4
gpt4 key购买 nike

我目前在json对象中进行深度搜索时遇到问题,尽管我认为这个问题一定已经解决了,但到目前为止我找不到任何真正有用的东西(而且我实际上也发现了很多东西, this thread。也许我今天看代码已经太久了,但这并没有真正帮助我)

基本上我想要的很简单。我有一个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;
}


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

克里斯问候

最佳答案

安全的深层物体搜索?

不能让它传递带有示例的3个答案,所有这些都有缺陷。所有这些都说明了一些经典的Javascript编码-

null是一个对象

更新答案已更改。

因为代码不再可见,所以我将在迭代对象的属性时留下警告,并且使用typeof来检查是否有对象,请小心检查null,因为它也是"object"类型

 getObject回到较早状态,无法找到嵌套在满足条件的对象内的其他对象。尽管通过删除返回值很容易解决,但是如果要搜索的对象中包含带有null的数组,它仍然会抛出TypeError: Cannot read property 'find' of null

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;
}





不要相信回调。

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;


如果将其作为参数传递,则会使所有其他答案崩溃。循环引用非常普遍。

一些解决方案。


第一种解决方案是仅接受JSON字符串形式的数据,并以JSON字符串形式相等地返回数据(这样就可以保持平衡,并且Universe不会爆炸)。因此消除了任何循环引用的机会。
跟踪递归深度并设置一个限制。虽然这将阻止调用栈溢出
浅循环引用可以创建重复的对象引用,因此不会阻止结果出错。
快速而又肮脏的解决方案是一个简单的尝试,它可以为数据总线那侧的对象捕获JSON.stringify和 throw TypeError("Object can not be searched");
最好的解决方案是回收对象。在这种情况下,这非常适合我们使用的实际算法。对于遇到的每个唯一对象,我们将其放置在数组中。如果遇到该数组中的对象,我们将忽略它并继续前进。




一个可能的解决方案。

因此,通用的解决方案是安全的(我希望)并且是灵活的。尽管它是为ES6编写的,所以必须以babel或类似形式提供传统支持。虽然它确实带有一个但是!



// Log function 
function log(data){console.log(data)}

// The test data
var a = {
a : "a",
one : {
two : {
find : "me",
data : "and my data in one.two"
},
twoA : {
four : 4,
find : "me",
data : "and my data in one.twoA"
}
},
two : {
one : {
one : 1,
find : "not me",
},
two : {
one : 1,
two : 1,
find : "me",
data : "and my data in two.two"
},
},
anArray : [
null,0,undefined,/./,new Date(),function(){return hi},
{
item : "one",
find : "Not me",
},{
item : "two",
find : "Not me",
extra : {
find : "me",
data : "I am a property of anArray item 1",
more : {
find : "me",
data : "hiding inside me"
},
}
},{
item : "three",
find : "me",
data : "and I am in an array"
},{
item : "four",
find : "me",
data : "and I am in an array"
},
],
three : {
one : {
one : 1,
},
two : {
one : 1,
two : 1,
},
three : {
one : 1,
two : {
one : {
find : "me",
data : "and my data in three.three.two.one"
}
}
}
},
}

// Add cyclic referance
a.extra = {
find : "me",
data : "I am cyclic in nature.",
}
a.extra.cycle = a.extra;
a.extraOne = {
test : [a],
self : a,
findme : a.extra,
};




if(! Object.allWith){
/* Non writeable enumerable configurable property of Object.prototype
as a function in the form
Object.allWith(predicate)
Arguments
predicate Function used to test the child property takes the argument
obj the current object to test
and will return true if the condition is meet
Return
An array of all objects that satisfy the predicate

Example

var test = {a : { key : 10, data: 100}, b : { key : 11, data: 100} };
var res = test.allWith((obj)=>obj.key === 10);
// res contains test.a
*/
Object.defineProperty(Object.prototype, 'allWith', {
writable : false,
enumerable : false,
configurable : false,
value : function (predicate) {
var uObjects = [];
var objects = [];
if (typeof predicate !== "function") {throw new TypeError("predicate is not a function")}
(function find (obj) {
var key;
if (predicate(obj) === true) {objects.push(obj)}
for (key of Object.keys(obj)) {
let o = obj[key];
if (o && typeof o === "object") {
if (! uObjects.find(obj => obj === o)) {
uObjects.push(o);
find(o);
}
}
}
} (this));
return objects;
}
});
}else{
console.warn("Warn!! Object.allWith already defined.");
}

var res = a.allWith(obj => obj.find === "me");
res.forEach((a,i)=>(log("Item : " + i + " ------------"),log(a)))





为什么要搜索未知的数据结构?

它适用于我可以提出的所有测试用例,但这根本不是确定的测试。我将其添加到 Object.prototype,因为您不应该这样做!!!也不使用此类函数或其派生词。

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

关于javascript - 深度搜索JSON对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42252538/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com