在JavaScript中递归遍历数组并修改对象属性的值
这篇文章可能看起来很长,但很容易理解,如果没有,我会补充更多细节 我有在JavaScript中递归遍历数组并修改对象属性的值,javascript,node.js,algorithm,recursion,data-structures,Javascript,Node.js,Algorithm,Recursion,Data Structures,这篇文章可能看起来很长,但很容易理解,如果没有,我会补充更多细节 我有标准数组,它看起来像: let criteria = [ "and", { "Collection": "persons", "Property": "phone", "operator": "eq&q
标准
数组,它看起来像:
let criteria = [
"and",
{
"Collection": "persons",
"Property": "phone",
"operator": "eq",
"operatorValue": "$p:phone"
},
{
"Collection": "persondetails",
"Property": "country",
"operator": "eq",
"operatorValue": "$p:country"
},
["or",
{
"Collection": "persons",
"Property": "city",
"operator": "eq",
"operatorValue": "$p:city"
}]
]
标准的特征:
[
"and",
{
"Collection": "persons",
"Property": "phone",
"operator": "eq",
"operatorValue": "23138213"
},
{
"Collection": "persondetails",
"Property": "country",
"operator": "eq",
"operatorValue": "Russia"
},
["or",
{
"Collection": "persons",
"Property": "city",
"operator": "eq",
"operatorValue": "york"
}]
]
function traverse(obj,parameters){
obj.forEach((item,index)=>{
if( typeof item == 'string' ){
//do nothing
}
else if( !(item instanceof Array)){
Object.entries(item).forEach((item,index)=>{
if( item[1] instanceof Array){
traverse(item,parameters);
}else{
if(item[1].startsWith('$p:')){
item[1]=parameters[item[1].split('$p:')[1]] //values dont get replaced for obvious reason
console.log(item[1])
}
}
})
}
else if( item instanceof Array){
traverse(item,parameters);
}
})
}
traverse(criteria,parameters)
console.log(criteria)
{“集合”:“个人”、“财产”:“电话”、“运营商”:“eq”、“运营商价值”:“$p:phone”}
或者它可以是一个数组,如:
[“或”、{“集合”:“人员”、“财产”:“城市”、“运营商”:“eq”、“运营商价值”:“$p:city”}]
参数对象:
let parameters = {phone:"23138213", "country": "Russia", "city":"york"}
其目的是递归遍历条件
数组中的所有运算符值
属性,如果遇到值,如$p:phone
,则该值将替换为计算到的任何参数[“phone”]
预期输出:
[
"and",
{
"Collection": "persons",
"Property": "phone",
"operator": "eq",
"operatorValue": "23138213"
},
{
"Collection": "persondetails",
"Property": "country",
"operator": "eq",
"operatorValue": "Russia"
},
["or",
{
"Collection": "persons",
"Property": "city",
"operator": "eq",
"operatorValue": "york"
}]
]
function traverse(obj,parameters){
obj.forEach((item,index)=>{
if( typeof item == 'string' ){
//do nothing
}
else if( !(item instanceof Array)){
Object.entries(item).forEach((item,index)=>{
if( item[1] instanceof Array){
traverse(item,parameters);
}else{
if(item[1].startsWith('$p:')){
item[1]=parameters[item[1].split('$p:')[1]] //values dont get replaced for obvious reason
console.log(item[1])
}
}
})
}
else if( item instanceof Array){
traverse(item,parameters);
}
})
}
traverse(criteria,parameters)
console.log(criteria)
我能够递归地遍历数组。唯一的问题是我不知道如何修改原始的标准变量
请参见回复中的第43行<代码>项目[1]=参数[项目[1]。拆分(“$p:”)[1]
我理解为什么它不会修改标准,因为这里的项在不同的范围内是一个不同的变量
尝试失败:
[
"and",
{
"Collection": "persons",
"Property": "phone",
"operator": "eq",
"operatorValue": "23138213"
},
{
"Collection": "persondetails",
"Property": "country",
"operator": "eq",
"operatorValue": "Russia"
},
["or",
{
"Collection": "persons",
"Property": "city",
"operator": "eq",
"operatorValue": "york"
}]
]
function traverse(obj,parameters){
obj.forEach((item,index)=>{
if( typeof item == 'string' ){
//do nothing
}
else if( !(item instanceof Array)){
Object.entries(item).forEach((item,index)=>{
if( item[1] instanceof Array){
traverse(item,parameters);
}else{
if(item[1].startsWith('$p:')){
item[1]=parameters[item[1].split('$p:')[1]] //values dont get replaced for obvious reason
console.log(item[1])
}
}
})
}
else if( item instanceof Array){
traverse(item,parameters);
}
})
}
traverse(criteria,parameters)
console.log(criteria)
如何着手解决这个问题?您可以简化您的函数。您不需要遍历对象的条目。您也不需要拆分操作值
。属性
键中存在参数
的映射键
- 循环遍历数组中的每个项,并检查该项是否为
数组
- 如果是,则递归调用项目上的
遍历
- 如果它是一个对象,则使用
参数[val.property]
函数遍历(arr,参数){
用于(arr的施工项目){
if(阵列isArray(项目))
遍历(项目、参数)
else if(项目类型==='object')
item.operatorValue=参数[item.Property]
}
返回arr
}
让标准=[“和”],{集合:“人”,财产:“电话”,接线员:“eq”,接线员价值:$p:phone},{集合:“个人信息”,财产:“国家”,接线员:“eq”,接线员价值:$p:country”},[“或”,{集合:“人”,财产:“城市”,接线员:“eq”,接线员价值:$p:city”}],
参数={电话:“23138213”,“国家”:“俄罗斯”,“城市”:“约克”};
log(遍历(标准、参数))
您需要获取对象的键来分配值
功能遍历(obj,参数){
对象forEach(项目=>{
if(数组的项实例)返回遍历(项、参数);
如果(项目?.operatorValue?.startsWith($p:)){
item.operatorValue=参数[item.operatorValue.split(“$p:”)[1];
}
});
}
常数
标准=[“和”],{集合:“人”,财产:“电话”,接线员:“eq”,接线员价值:$p:phone”},{集合:“个人信息”,财产:“国家”,接线员:“eq”,接线员价值:$p:country”},[“或”,{集合:“人”,财产:“城市”,接线员:“eq”,接线员价值:$p:city”}],
参数={电话:“23138213”,“国家”:“俄罗斯”,“城市”:“约克”};
导线测量(标准、参数);
控制台日志(标准)代码>
.as控制台包装{max height:100%!important;top:0;}
一个干净的递归版本:
const traverse=([conj,…nodes],params)=>[
conj,
…nodes.map(node=>Array.isArray(node)
?导线测量(节点、参数)
:{…节点,运算符值:params[nodes.Property]}
)
]
const-criteria=[“and”],{集合:“person”,属性:“phone”,操作符:“eq”,操作符值:$p:phone”},{集合:“persondetails”,属性:“country”,操作符:“eq”,操作符值:$p:country”},[“or”,{集合:“person”,属性:“city”,操作符:“eq”,操作符值:$p:city”}]
const参数={电话:“23138213”,“国家”:“俄罗斯”,“城市”:“约克”}
console.log(遍历(标准、参数))
.as控制台包装{min height:100%!important;top:0}
下面是一个使用的解决方案。根据您的需求,可能会更加灵活和易于维护
//const objectScan=require('object-scan');
const-criteria=['and',{Collection:'persons',Property:'phone',operator:'eq',operator:'p:phone'},{Collection:'personates',Property:'city',operator:'eq',operator:'p:city'};
常量替换=(对象,参数)=>objectScan(['**.operatorValue']{
rtn:'计数',
filterFn:({value,parent,property})=>{
if(value.startsWith(“$p:”)&参数中的value.slice(3){
父级[属性]=参数[值.切片(3)];
返回true;
}
返回false;
}
})(obj);
log(替换(标准,{phone:'23138213',country:'rusia',city:'york');//返回替换数
// => 3
控制台日志(标准);
//=>['和',{收集:'人',财产:'电话',接线员:'eq',接线员价值:'23138213'},{收集:'persondetails',财产:'country',接线员:'eq',接线员价值:'york'},['或',{收集:'persons',财产:'city',接线员:'eq',接线员价值:'york'}]
。作为控制台包装{最大高度:100%!重要;顶部:0}
我想知道为什么这样做有效,但我的解决方案无效。是因为obj.forEach吗((