下面是我需要找到至少一次isSelected: true
。
[
{
"isSelected": true,
"child": [
{
"isSelected": true,
"child": [
{
"isSelected": true,
"child": [
{
"isSelected": true
}
]
}
]
}
]
}
]
上述对象中可以包含 n 元素,每个元素都可以包含 n 子元素,依此类推。对于每个元素,都会有一个isSelected
键,其值为“true / false”。
我正在尝试在JavaScript中编写一个函数,如果它发现至少有一个isSelected
键出现真值,它将返回true。
使用JSON.stringify()
写下面的函数并在其中搜索字符串“isSelected:true”字符串
function hasIsSelected(data){
return (JSON.stringify(data)).search('"isSelected":true') > -1 ? true: false
}
不确定JSON.stringify()
是否对大型对象有效。
尝试在不使用第三方库的情况下在JavaScript中找到解决方案。
答案 0 :(得分:2)
您可以使用递归算法来检查" isSelected"价值并循环所有孩子:
function hasIsSelected(data) {
if (data.isSelected) {
return true;
}
if (data.child) {
for (var i = 0; i < data.child.length; i++) {
if (hasIsSelected(data.child[i])) {
return true;
}
}
}
return false;
}
var json = [...]; // Your value
hasIsSelected(json[0]);
编辑: 好吧,让我们为最坏的情况制作一个非常简单的基准:
function createTestData(depth) {
var obj = { isSelected: depth === 0 };
if (depth > 0) {
obj.child = [createTestData(depth - 1)];
}
return obj;
}
var testData = [createTestData(1000)]; // Big object, the "true" value is in the deepest child.
function hasIsSelectedStrinfigy(data){
return (JSON.stringify(data)).search('"isSelected":true') > -1;
}
function hasIsSelectedRec(data) {
if (data.isSelected) {
return true;
}
if (data.child) {
for (var i = 0; i < data.child.length; i++) {
if (hasIsSelectedRec(data.child[i])) {
return true;
}
}
}
return false;
}
// Using NicolaeS's solution
function hasIsSelectedRecTOC(data) {
if (data.isSelected === true) {
return true;
}
if (data.child instanceof Array) {
// stops after the first valid element
return data.child.some(hasIsSelectedRecTOC);
}
return false;
}
// Run tests
function runTest(fun) {
var t0 = performance.now();
fun(testData[0]);
var t1 = performance.now();
return t1 - t0;
}
console.log("Exec time using stringify : %o", runTest(hasIsSelectedStrinfigy));
console.log("Exec time using recursion : %o", runTest(hasIsSelectedRec));
console.log("Exec time using recursion with TOC : %o", runTest(hasIsSelectedRecTOC));
我的计算机上的结果(每次运行它们都会改变但你明白了):
Exec time using stringify : 6.785000000000004
Exec time using recursion : 0.36999999999999034
Exec time using recursion with TOC : 0.37999999999999545
这是最糟糕的情况。现在有了最好的情况(第一个是选择&#34;真&#34;):
function createTestData(depth) {
var obj = { isSelected: true }; // isSelected is always true
if (depth > 0) {
obj.child = [createTestData(depth - 1)];
}
return obj;
}
var testData = [createTestData(1000)];
结果:
Exec time using stringify : 3.980000000000002
Exec time using recursion : 0.040000000000000924
Exec time using recursion with TOC : 0.02499999999999858
答案 1 :(得分:1)
以@Junior的答案为基础 - 递归是最快的方法,但这是使用tail call optimization的更高性能版本:
function hasIsSelected(data) {
if (data.isSelected === true) {
return true;
} else if (data.child instanceof Array) {
return data.child.some(hasIsSelected); // stops after the first selected element
} else return false;
}
另一个重要技巧是在找到true
后立即停止循环。
答案 2 :(得分:1)
递归将是最好的方法:
const deepSearch = (arr) => {
return arr.some((v) => {
if (v.isSelected === true) {
return true;
}
if (Array.isArray(v.child) && v.child.length > 0) {
return deepSearch(v.child);
}
return false;
});
};
这是jsperf test。
已添加:Array.isArray(X)
比X instanceof Array
快约3.3倍。这是jsperf test confirming that。