JavaScript中的递归以在重JSON中搜索
我面临一个算法概念问题。使用JavaScript语言,我有一个大约11000行的重JSON对象,这是HTML文件转换的结果。JSON的结构类似于DOM的结构,这意味着一个对象可以有一个属性子对象,一个由其他类似对象组成的数据结构。目标是在JSON中搜索并提取具有该属性的对象的属性itemprop的信息。itemprop属性位于前面提到的一些对象所具有的attributes属性中,而Object位于attributes属性中 对象结构JavaScript中的递归以在重JSON中搜索,javascript,json,algorithm,recursion,bigdata,Javascript,Json,Algorithm,Recursion,Bigdata,我面临一个算法概念问题。使用JavaScript语言,我有一个大约11000行的重JSON对象,这是HTML文件转换的结果。JSON的结构类似于DOM的结构,这意味着一个对象可以有一个属性子对象,一个由其他类似对象组成的数据结构。目标是在JSON中搜索并提取具有该属性的对象的属性itemprop的信息。itemprop属性位于前面提到的一些对象所具有的attributes属性中,而Object位于attributes属性中 对象结构 { type: 'x', tagName: 'y',
{ type: 'x',
tagName: 'y',
attributes: { "itemprop" : "valueWanted" },
children:
[ Object, Object, Object]
}
{
"type": "",
"tagName": "",
"attributes": {
"itemprop": "wantedValue"
},
"children": [{
"type": "",
"content": ""
}
]
},
{
"type": "",
"content": ""
}]
},
{
"type": "",
"tagName": "",
"attributes": {},
"children": [
{
"type": "",
"content": "here"
}
]
我想到了一个递归算法来解决这个问题。不幸的是,我不熟悉递归,下一个代码不起作用
递归算法
var searchAttributesRecursive = function(children) {
for (var i = 0; i < children.length; ++i) {
if (children[i].hasOwnProperty('children')) {
return searchAttributesRecursive(children[i].children);
}
else {
if (children[i].hasOwnProperty('attributes')) {
if (children[i].attributes.itemprop === "valueWanted") {
console.log('success')
}
}
}
return; // probably a problem that breaks the loop
}
};
searchAttributesRecursive(startingChildren);
你的回归将打破循环。如果它确实返回,您只想返回:
var searchAttributesRecursive = function(children) {
for (var i = 0; i < children.length; ++i) {
if (children[i].hasOwnProperty('children')) {
var result=searchAttributesRecursive(children[i].children);
if(result) return result;//if weve found sth, return
}
if (children[i].hasOwnProperty('attributes')) {
if (children[i].attributes.itemprop === "valueWanted1") {
console.log('success')
return children[i];//return sth useful
}
}
}
return false;//nothing found in this and in all childs
};
var elem=searchAttributesRecursive(startingChildren);
以下是一个简短的版本: 请注意,函数需要一个数组,因此如果对象不是数组,则必须使用
findItemprop([dom],“wanted”)
函数findItemprop(数据、值、已找到){
如果(!found)found=[];
data.forEach((节点)=>{
if(node.attributes&&node.attributes.itemprop==value)
发现.推送(节点);
if(node.children)findItemprop(node.children,value,found);
});
发现退货;
}
变量dom=[{
标签:“根”,
儿童:[{
标签:“标题”,
儿童:[{
标签:“div”
}]
}, {
标签:“div”,
id:“主要”,
儿童:[{
标签:“p”,
属性:{
itemprop:“通缉”
}
}]
}, {
标签:“页脚”,
儿童:[{
标签:“span”,
内容:“版权所有2017”,
属性:{
itemprop:“通缉”
}
}]
}]
}];
log(findItemprop(dom,“通缉”)代码>您可以使用.some()
函数来完成此操作。如果任何迭代返回true,它将返回true,否则它将返回false。因此,对于当前对象中的每个键,您将检查属性是否为==“attributes”
,如果是,您将检查itemprop
属性以获得所需的值。如果当前键不是“attributes”,而是“children”
,它将以相同的方式递归并检查每个子对象
var searchAttributesRecursive=函数(obj,valueWanted){
if(对象的obj实例){
if(obj.attributes&&obj.attributes.itemprop==valueWanted){
返回true;
}
if(对象儿童){
返回obj.children.some(函数(_obj){
返回searchAttributesRecursive(_obj,valueWanted);
});
}否则{
返回false;
}
}否则{
返回false;
}
};
var obj={
键入:“x”,
标记名:“y”,
属性:{
“itemprop”:“wantedValue0”
},
儿童:[{
键入:“x”,
标记名:“y”,
属性:{
“itemprop”:“wantedValue1”
},
儿童:[]
},
{
键入:“x”,
标记名:“y”,
属性:{
“itemprop”:“wantedValue2”
},
儿童:[{
键入:“x”,
标记名:“y”,
属性:{
“itemprop”:“wantedValue3”
},
儿童:[]
}]
}
]
};
log(“找到'wantedValue0':”+searchAttributesRecursive(obj,“wantedValue0”);
log(“找到‘wantedValue1’:”+searchAttributesRecursive(obj,“wantedValue1”));
log(“找到‘wantedValue2’:”+searchAttributesRecursive(obj,“wantedValue2”));
log(“找到'wantedValue3':”+searchAttributesRecursive(obj,“wantedValue3”);
log(“找到‘wantedValue4’:”+searchAttributesRecursive(obj,“wantedValue4”))代码>给Jonas w他们的答案加上一点功劳,我只是想帮助纠正围绕递归的一些困惑,希望能让它更容易理解和使用
首先,您将传递一组子对象。这很好,但是在检查它们时,必须从其数组索引中访问它们。我的建议是让函数一次只处理一项。(我将使用Jonas w收集节点的方法,因为可能有多个节点具有此属性。我还将添加属性名称作为参数,使其更具动态性。)
现在您可以一次只关注一个节点。一旦它通过了检查,你就可以继续看孩子们了
function searchAttributesRecursive(currentNode, parameterName, results=[]){
if(currentNode.attributes && currentNode.attributes[parameterName]){
results.push(currentNode);
}
if(currentNode.children){
for(var i = 0, len = currentNode.children.length; i < len; ++i){
searchAttributesRecursive(currentNode.children[i], parameterName, results);
}
}
}
…使用包含“itemprop”属性的节点填充结果
。现在可以使用简单的循环打印属性值:
for(var i = 0, len = results.length; i < len; ++i){
console.log(i, results[i].attributes.itemprop);
}
for(变量i=0,len=results.length;i
搜索,真的吗?它看起来像一个对象,您正在处理。请添加结构,至少一小部分,它是如何构造的。你真的在寻找字符串“itemprop”@NinaScholz JSON对象已转换为JS对象,不是吗?我添加了对象结构。对象可以有attributes或children属性。@epascarello是的。由于Nina链接,JSON只是一种文本格式。这是一根绳子。除了JSON
内置JavaScript对象之外,没有所谓的“JSON对象”。但是是的,JSON.parse
将JSON字符串转换为JavaScript对象。这是一个很小但很重要的区别。重命名children
参数(而不是属性)可能有助于缓解围绕递归的一些amazingcode12的困惑children[i]。children
==混乱,current[i]。children
==不那么混乱。@TheJim01我认为这对OP是一个很好的建议。但是,我希望他的代码看起来相似,这样更容易理解…@Jonasw看起来属性没有定义(TypeError:无法读取未定义的属性'itemprop'))@这是不可能的。它以前在队列中检查过吗?@Jonasw谢谢,它现在正在工作,我知道
function searchAttributesRecursive(currentNode, parameterName, results=[]){
}
function searchAttributesRecursive(currentNode, parameterName, results=[]){
if(currentNode.attributes && currentNode.attributes[parameterName]){
results.push(currentNode);
}
if(currentNode.children){
for(var i = 0, len = currentNode.children.length; i < len; ++i){
searchAttributesRecursive(currentNode.children[i], parameterName, results);
}
}
}
var results = [];
searchAttributesRecursive(yourJsObject, "itemprop", results);
for(var i = 0, len = results.length; i < len; ++i){
console.log(i, results[i].attributes.itemprop);
}