Javascript 在对象或数组中查找字符串的路径

Javascript 在对象或数组中查找字符串的路径,javascript,recursion,Javascript,Recursion,给定一个对象或数组,我希望能够确定该路径是否存在 给定-示例1 const spath = "data/message"; const body = { data: { school: 'yaba', age: 'tolu', message: 'true' }, time: 'UTC', class: 'Finals' } 它应该返回true,因为可以在body.data.message else中找到消息,否则返回false 给定

给定一个对象或数组,我希望能够确定该路径是否存在

给定-示例1

const spath = "data/message";
const body = {
  data: {
    school: 'yaba',
    age: 'tolu',
    message: 'true'
  },
  time: 'UTC',
  class: 'Finals'
}
它应该返回true,因为可以在body.data.message else中找到消息,否则返回false

给定-示例2

const spath = "data/message/details/lastGreeting";
const body = {
  data: {
    school: 'yaba',
    age: 'tolu',
    message: {
       content: 'now',
       details: {
          lastGreeting: true
       }
    }
  },
  time: 'UTC',
  class: 'Finals'
}
它应该返回true,因为可以在body.data.message.details.lastGreeting中找到lastGreeting,否则返回false

另一种情况是主体由数组组成

给定-示例3

const spath = "data/area/NY";
const body = {
  data: {
    school: 'yaba',
    age: 'tolu',
    names : ['darious'],
    area: [{
       NY: true,
       BG: true
    ]]
    message: {
       content: 'now',
       details: {
          lastGreeting: true
       }
    }
  },
  time: 'UTC',
  class: 'Finals'
}
它应该返回true,因为可以在body.data.area[0]中找到NY。否则,NY将返回false

这就是我想出的解决办法

const findPathInObject = (data, path, n) => {
  console.log('entered')
  console.log(data, path)
  

  if(!data){
    return false
  }
  
  let spath = path.split('/');
  for(let i = 0; i<n; i++){
    
    let lastIndex = spath.length - 1;
    if(spath[i] in data && spath[i] === spath[lastIndex]){
      return true
    }
    
    const currentIndex = spath[i];
//     spath.splice(currentIndex, 1);
    return findPathInObject(data[spath[currentIndex]], spath[i+1], spath.length)
    
  }
  
  return false
}

console.log(findPathInObject(body, spath, 3))

您可以提前进行一些检查,检查path是否为临时字符串,然后使用true退出

通过拥有一个数组,您可以通过省略索引来使用实际路径检查数组的元素,从而提前退出

对于键的最终检查,您可以检查它是否存在,并使用rest路径返回Recurseve调用的结果,如果键不在对象中,则返回false

常数 FindPathinoObject=数据,路径=>{ 如果!路径返回true; 如果!data | | typeof data!=“object”返回false; 如果Array.isArraydata返回data.somed=>findPathInObjectd,则为path; 常数 spath=路径分割“/”, 键=spath.shift; 返回数据中的键 ?findPathInObjectdata[key],spath.join'/' :假; }; console.logfindPathInObject{data:{学校:'yaba',年龄:'tolu',消息:'true'},时间:'UTC',班级:'Finals'},数据/消息,3;//符合事实的 console.logfindPathInObject{data:{school:'yaba',age:'tolu',message:{content:'now',details:{lastGreeting:true}}}},time:'UTC',class:'Finals'},data/message/details/lastGreeting,3;//符合事实的
console.logfindPathInObject{数据:{学校:'yaba',年龄:'tolu',姓名:['darious',区域:[{NY:true,BG:true}],消息:{内容:'now',细节:{lastGreeting:true}}}},时间:'UTC',班级:'final'},数据/区域/NY,3;//true您可以提前进行一些检查,检查path是否为临时字符串,然后使用true退出

通过拥有一个数组,您可以通过省略索引来使用实际路径检查数组的元素,从而提前退出

对于键的最终检查,您可以检查它是否存在,并使用rest路径返回Recurseve调用的结果,如果键不在对象中,则返回false

常数 FindPathinoObject=数据,路径=>{ 如果!路径返回true; 如果!data | | typeof data!=“object”返回false; 如果Array.isArraydata返回data.somed=>findPathInObjectd,则为path; 常数 spath=路径分割“/”, 键=spath.shift; 返回数据中的键 ?findPathInObjectdata[key],spath.join'/' :假; }; console.logfindPathInObject{data:{学校:'yaba',年龄:'tolu',消息:'true'},时间:'UTC',班级:'Finals'},数据/消息,3;//符合事实的 console.logfindPathInObject{data:{school:'yaba',age:'tolu',message:{content:'now',details:{lastGreeting:true}}}},time:'UTC',class:'Finals'},data/message/details/lastGreeting,3;//符合事实的 console.logfindPathInObject{数据:{学校:'yaba',年龄:'tolu',姓名:['darious',区域:[{NY:true,BG:true}],消息:{内容:'now',细节:{lastGreeting:true}}}},时间:'UTC',班级:'final'},数据/区域/NY,3;//true严格来说,body.data.area[0].NY不在body的路径中,对不起。body.data.area位于路径中。对于没有body.data.area作为数组的对象,这里有一个解决方案。如果要将数组中的对象作为对象路径的一部分包含在内,则解决方案将更加复杂

常数spath=数据/面积/NY; const spath2=数据/消息/详细信息/最新问候语; const notPath=data/message/details/firstGreeting; 常数体={ 数据:{ 学校:'雅巴', 年龄:"吐露港",, 姓名:[“darious”], 面积:{ 纽约:是的, BG:没错 }, 信息:{ 内容:"现在",, 详情:{ 最后的问候:真的 } } }, 时间:“UTC”, 课程:“决赛” }; console.log`${spath}是否存在${existsbody,spath&'yes`| |'nope`}; console.log`${spath2}是否存在${existsbody,spath2&'yes`| |'nope`}; console.log`${notPath}是否存在${existsbody,notPath&'yes`| |'nope`}; 函数existsobj,路径{ const pathIterable=path.split/; 而可悲的长度{ const current=pathitable.shift; //没有路径剩余且存在:true 如果pathIterable.length<1&¤t in obj{return true;} //到目前为止,路径仍然存在:递归 如果对象{return existsobj[current],pathIterable.join/;}中的当前值 } //未找到解决方案:false 返回false; } 严格来说,body.data.area[0].NY不在body的路径中,抱歉。body.data.area位于路径中。对于没有body.data.area作为数组的对象,这里有一个解决方案。如果要在arr中包含对象 作为对象路径的一部分,解决方案将更加复杂

常数spath=数据/面积/NY; const spath2=数据/消息/详细信息/最新问候语; const notPath=data/message/details/firstGreeting; 常数体={ 数据:{ 学校:'雅巴', 年龄:"吐露港",, 姓名:[“darious”], 面积:{ 纽约:是的, BG:没错 }, 信息:{ 内容:"现在",, 详情:{ 最后的问候:真的 } } }, 时间:“UTC”, 课程:“决赛” }; console.log`${spath}是否存在${existsbody,spath&'yes`| |'nope`}; console.log`${spath2}是否存在${existsbody,spath2&'yes`| |'nope`}; console.log`${notPath}是否存在${existsbody,notPath&'yes`| |'nope`}; 函数existsobj,路径{ const pathIterable=path.split/; 而可悲的长度{ const current=pathitable.shift; //没有路径剩余且存在:true 如果pathIterable.length<1&¤t in obj{return true;} //到目前为止,路径仍然存在:递归 如果对象{return existsobj[current],pathIterable.join/;}中的当前值 } //未找到解决方案:false 返回false;
} 您可以检查此解决方案。还将检查对象数组

常数体={ 数据:{ 学校:'雅巴', 年龄:"吐露港",, 信息:{ 内容:"现在",, 详情:{ 最后的问候:是的, }, }, 面积:[ { 纽约:是的, BG:没错, }, ], }, 时间:“UTC”, 班级:'期末考试', }; 常量spath1='数据/消息'; const spath2='data/message/details/lastGreeting'; 常量spath3='数据/区域/纽约'; 常量spath4='数据/区域/纽约/测试'; console.log`${spath1}:`,isPathExistsbody,spath1.split'/',0; console.log`${spath2}:`,isPathExistsbody,spath2.split'/',0; console.log`${spath3}:`,isPathExistsbody,spath3.split'/',0; console.log`${spath4}:`,isPathExistsbody,spath4.split'/',0; 函数ispathexistdata,pathArr,i{ const key=pathArr[i]; if Array.isArraydata{ 数据的let值{ 如果isObjectvalue返回值为PathExistsValue,则为pathArr,i; } }否则,如果data.hasOwnPropertykey{ 如果key===pathArr[pathArr.length-1]返回true; 返回ispathexistdata[key],pathArr,i+1; }否则返回false; 返回true; } 等深线函数{ return!!a&&a.constructor==对象;
} 您可以检查此解决方案。还将检查对象数组

常数体={ 数据:{ 学校:'雅巴', 年龄:"吐露港",, 信息:{ 内容:"现在",, 详情:{ 最后的问候:是的, }, }, 面积:[ { 纽约:是的, BG:没错, }, ], }, 时间:“UTC”, 班级:'期末考试', }; 常量spath1='数据/消息'; const spath2='data/message/details/lastGreeting'; 常量spath3='数据/区域/纽约'; 常量spath4='数据/区域/纽约/测试'; console.log`${spath1}:`,isPathExistsbody,spath1.split'/',0; console.log`${spath2}:`,isPathExistsbody,spath2.split'/',0; console.log`${spath3}:`,isPathExistsbody,spath3.split'/',0; console.log`${spath4}:`,isPathExistsbody,spath4.split'/',0; 函数ispathexistdata,pathArr,i{ const key=pathArr[i]; if Array.isArraydata{ 数据的let值{ 如果isObjectvalue返回值为PathExistsValue,则为pathArr,i; } }否则,如果data.hasOwnPropertykey{ 如果key===pathArr[pathArr.length-1]返回true; 返回ispathexistdata[key],pathArr,i+1; }否则返回false; 返回true; } 等深线函数{ return!!a&&a.constructor==对象; } 发现

对于这个答案,我将提供一个具有不同程度的对象和数组嵌套的树-

常数树= {数据: {学校:雅巴,年龄:托鲁,留言:福} ,类别: [{name:math},{name:science}] ,深: [{例如: [{nested:hello} ,{nested:world} ] } ] } 发电机非常适合解决这类问题。从生成特定路径的所有可能结果的通用查找开始-

函数查找数据、路径 {函数*循环t,[k,…更多] {如果t==null返回 如果k==null,则产生t else开关t?构造函数 {案例对象: 收益率*loopt[k],更多 打破 案例阵列: t的常数v 收益率*loopv,[k,…更多] 打破 } } 返回loopdata,path.split/ } Array.fromfindtree,类/名称 Array.fromfindtree,deep/example/nested Array.fromfindtree,x/y/z [数学、科学] [你好,世界] [] 查找1

如果您想要一个返回第一个结果的函数,我们可以很容易地编写find1。这尤其有效,因为生成器是可暂停/可取消的。找到第一个结果后,生成器将停止搜索其他re 苏丹-

函数find1数据,路径 {对于finddata的常量结果,路径 返回结果 } Find1树、数据/学校 find1树,类 find1tree,类/名称 find1tree,深/示例/嵌套 Find1树,x/y/z 雅巴 [{name:math},{name:science}] 数学 你好 未定义 存在

如果您想检查特定路径是否存在,我们可以将exists写为find1的一个简单专门化-

const exists=数据,path=> Find1数据,路径!==未定义 现有资料/学校 现存的,阶级的 existstree,深/示例/嵌套 出口,x/y/z 符合事实的 符合事实的 符合事实的 错误的 演示

展开下面的代码段,在您自己的浏览器中验证结果-

函数查找数据、路径 {函数*循环t,[k,…更多] {如果t==null返回 如果k==null,则产生t else开关t?构造函数 {案例对象: 收益率*loopt[k],更多 打破 案例阵列: t的常数v 收益率*loopv,[k,…更多] 打破 } } 返回loopdata,path.split/ } 函数find1数据,路径 {对于finddata的常量结果,路径 返回结果 } 常数树= {数据: {学校:雅巴,年龄:托鲁,留言:福} ,类别: [{name:math},{name:science}] ,深: [{例如: [{nested:hello} ,{nested:world} ] } ] } console.logfind1 console.LogFind1树,数据/学校 console.logfind1tree,类 console.logfind1树,类/名称 console.logfind1tree,deep/example/nested console.logfind1tree,x/y/z console.logfind console.logArray.fromfindtree,类/名称 console.logArray.fromfindtree,深/示例/嵌套 console.logArray.fromfindtree,x/y/zfind

对于这个答案,我将提供一个具有不同程度的对象和数组嵌套的树-

常数树= {数据: {学校:雅巴,年龄:托鲁,留言:福} ,类别: [{name:math},{name:science}] ,深: [{例如: [{nested:hello} ,{nested:world} ] } ] } 发电机非常适合解决这类问题。从生成特定路径的所有可能结果的通用查找开始-

函数查找数据、路径 {函数*循环t,[k,…更多] {如果t==null返回 如果k==null,则产生t else开关t?构造函数 {案例对象: 收益率*loopt[k],更多 打破 案例阵列: t的常数v 收益率*loopv,[k,…更多] 打破 } } 返回loopdata,path.split/ } Array.fromfindtree,类/名称 Array.fromfindtree,deep/example/nested Array.fromfindtree,x/y/z [数学、科学] [你好,世界] [] 查找1

如果您想要一个返回第一个结果的函数,我们可以很容易地编写find1。这尤其有效,因为生成器是可暂停/可取消的。找到第一个结果后,生成器将停止搜索其他结果-

函数find1数据,路径 {对于finddata的常量结果,路径 返回结果 } Find1树、数据/学校 find1树,类 find1tree,类/名称 find1tree,深/示例/嵌套 Find1树,x/y/z 雅巴 [{name:math},{name:science}] 数学 你好 未定义 存在

如果您想检查特定路径是否存在,我们可以将exists写为find1的一个简单专门化-

const exists=数据,path=> Find1数据,路径!==未定义 现有资料/学校 现存的,阶级的 existstree,深/示例/嵌套 出口,x/y/z 符合事实的 符合事实的 符合事实的 错误的 演示

展开下面的代码段,在您自己的浏览器中验证结果-

函数查找数据、路径 {函数*循环t,[k,…更多] {如果t==null返回 如果k==null,则产生t else开关t?构造函数 {案例对象: 收益率*loopt[k],更多 打破 案例阵列: t的常数v 收益率*loopv,[k,…更多] 打破 } } 返回loopdata,path.split/ } 函数find1数据,路径 {对于finddata的常量结果,路径 返回结果 } 常数树= {数据: {学校:雅巴,年龄:托鲁,留言:福} ,类别: [{name:math},{name:science}] ,深: [{例如: [{nested:hello} ,{nested:world} ] } ] } console.logfind1 console.LogFind1树,数据/学校 console.logfind1tree,类 console.logfind1树,类/名称 console.logfind1tree,deep/example/nested console.logfind1tree,x/y/z console.logfind console.logArray.fromfindtree,类/名称 console.logArray.fromfindtree,深/示例/嵌套
console.logArray.fromfindtree,x/y/z在一位同事的帮助下,我们终于想出了一些简单易懂的东西,真正适合我们的需要。使用yield实现的答案解决了这个问题,但我们一直在寻找一些可以在代码库中阅读并容易理解的东西。我们希望能够检查对象中是否存在路径,并获取值

因此,我们添加了第三个参数returnValue——默认情况下,它将始终返回值。如果我们不希望它这样做,我们可以将返回值的值设置为false,函数将检查路径是否存在,如果存在,它将返回true,否则返回false

这就是我们最终得出的结论

const findPathInObject = (data, path, n) => {
  console.log('entered')
  console.log(data, path)
  

  if(!data){
    return false
  }
  
  let spath = path.split('/');
  for(let i = 0; i<n; i++){
    
    let lastIndex = spath.length - 1;
    if(spath[i] in data && spath[i] === spath[lastIndex]){
      return true
    }
    
    const currentIndex = spath[i];
//     spath.splice(currentIndex, 1);
    return findPathInObject(data[spath[currentIndex]], spath[i+1], spath.length)
    
  }
  
  return false
}

console.log(findPathInObject(body, spath, 3))
const find=路径,data=>{ if Array.isArraydata{ 数据=数据[0]; } 对于数据中的常量项{ 如果项===路径{ 返回数据[项目]; } } 返回null; }; const findPath=fullPath,fullData,returnValue=true=>{ const pathArray=fullPath.split“/”; 让findResult=fullData; 用于pathArray的常量pathItem{ findResult=findpathItem,findResult; 如果!findResult{ 如果!returnValue返回false; 返回null; } } 如果!returnValue返回true; 返回findResult; }; 常数体={ 名字:“迈克”, 电邮:1,, 数据:{ 学校:[ { 测试:123 } ] } } 控制台。logfindPath“数据/学校/测试”,正文
在一位同事的帮助下,我们终于想出了一些简单易懂的东西,真正适合我们的需要。使用yield实现的答案解决了这个问题,但我们一直在寻找一些可以在代码库中阅读并容易理解的东西。我们希望能够检查对象中是否存在路径,并获取值

因此,我们添加了第三个参数returnValue——默认情况下,它将始终返回值。如果我们不希望它这样做,我们可以将返回值的值设置为false,函数将检查路径是否存在,如果存在,它将返回true,否则返回false

这就是我们最终得出的结论

const findPathInObject = (data, path, n) => {
  console.log('entered')
  console.log(data, path)
  

  if(!data){
    return false
  }
  
  let spath = path.split('/');
  for(let i = 0; i<n; i++){
    
    let lastIndex = spath.length - 1;
    if(spath[i] in data && spath[i] === spath[lastIndex]){
      return true
    }
    
    const currentIndex = spath[i];
//     spath.splice(currentIndex, 1);
    return findPathInObject(data[spath[currentIndex]], spath[i+1], spath.length)
    
  }
  
  return false
}

console.log(findPathInObject(body, spath, 3))
const find=路径,data=>{ if Array.isArraydata{ 数据=数据[0]; } 对于数据中的常量项{ 如果项===路径{ 返回数据[项目]; } } 返回null; }; const findPath=fullPath,fullData,returnValue=true=>{ const pathArray=fullPath.split“/”; 让findResult=fullData; 用于pathArray的常量pathItem{ findResult=findpathItem,findResult; 如果!findResult{ 如果!returnValue返回false; 返回null; } } 如果!returnValue返回true; 返回findResult; }; 常数体={ 名字:“迈克”, 电邮:1,, 数据:{ 学校:[ { 测试:123 } ] } } 控制台。logfindPath“数据/学校/测试”,正文
下面是一个使用

//const objectScan=需要“对象扫描”; const data1={data:{学校:'yaba',年龄:'tolu',消息:'true'},时间:'UTC',班级:'Finals'}; const data2={数据:{学校:'yaba',年龄:'tolu',信息:{内容:'now',详细信息:{lastGreeting:true}}}}},时间:'UTC',班级:'Finish'}; const data3={数据:{学校:'yaba',年龄:'tolu',姓名:['darious',区域:[{NY:true,BG:true}],消息:{内容:'now',详细信息:{lastGreeting:true}}},时间:'UTC',班级:'Final'}; 常量路径1='数据/消息'; const path2='data/message/details/lastGreeting'; 常量路径3='数据/区域/NY'; const exists=data,n=>objectScan[n.replace/\//g,'.'.']{ useArraySelector:false, rtn:‘bool’, 中止:正确 }数据; console.logexistsdata1,路径1; //=>正确 console.logexistsdata2,路径2; //=>正确 console.logexistsdata3,路径3; //=>正确 .作为控制台包装{最大高度:100%!重要;顶部:0}
下面是一个使用

//const objectScan=需要“对象扫描”; const data1={data:{学校:'yaba',年龄:'tolu',消息:'true'},时间:'UTC',班级:'Finals'}; const data2={数据:{学校:'yaba',年龄:'tolu',信息:{内容:'now',详细信息:{lastGreeting:true}}}}},时间:'UTC',班级:'Finish'}; const data3={数据:{学校:'yaba',年龄:'tolu',姓名:['darious',区域:[{NY:true,BG:true}],消息:{内容:'now',详细信息:{lastGreeting:true}}},时间:'UTC',班级:'Final'}; 常量路径1='数据/消息'; const path2='data/message/details/lastGreeting'; 常量路径3='数据/区域/NY'; const exists=data,n=>objectScan[n.replace/\//g,'.'.']{ useArraySelector:false, rtn:‘bool’, 中止:正确 }数据; console.logexistsdata1,路径1; //=>正确 console.logexistsdata2,路径2; //=>正确 console.logexistsdata3,路径3; //=>正确 .作为控制台包装{最大高度:100%!重要;顶部:0}
您面临的问题是什么?因为spath[i+1],最后一个索引发生了更改-我想防止这种情况发生。lastindex应始终是路径中的最后一项。还要为包含数组的对象做准备您想要递归解决方案吗?是的,递归解决方案可以解决问题,您面临的问题是什么?由于spath[i+1],最后一个索引发生了更改-我想防止出现这种情况。lastindex应始终是路径中的最后一项。另外,还要为中包含数组的对象做准备
Theme你想要一个递归解决方案吗?是的,递归解决方案会对牙齿起作用,当我尝试检查不存在的路径时,它会抛出一个错误,例如使用此路径-data/message/jdjfjdkf抛出一个错误类型错误:不能使用'in'运算符在True中搜索'jdjfjdkf'。你也需要检查一个对象。请参阅编辑。谢谢-我认为您的解决方案也涵盖了数组部分谢谢,当我尝试检查不存在的路径时,它会抛出一个错误,例如使用此路径-data/message/jdjfjdkf抛出一个错误类型错误:无法使用'in'运算符在True中搜索'jdjfjdkf'。您也需要检查一个对象。请参见编辑。谢谢-我认为您的解决方案也涵盖了阵列部分谢谢,body.data.area[0]。NY实际上不在路径中。我可以用这个。再次感谢Hanks,body.data.area[0]。NY实际上不在路径中。我可以用这个。感谢againNote,它只检查数组的第一个元素。虽然findPath'data/school/testing',{data:{school:[{testing:123}]}产生123,findPath'data/school/testing',{data:{school:[{noTesting:345},{testing:123}}产生null,即使第二个元素中有测试。如果这是你的要求,好的。但是如果没有,我建议您通过@Thankyou的答案可以学到很多。是的,它符合我们的要求。谢谢你的反馈。为了学习的目的,我可以改进它以适应这种情况。请问谁是@Thankyu?用户写了,并写了一些我在StackOverflow上看到的最鼓舞人心和信息丰富的答案。请注意,这只检查数组的第一个元素。虽然findPath'data/school/testing',{data:{school:[{testing:123}]}产生123,findPath'data/school/testing',{data:{school:[{noTesting:345},{testing:123}}产生null,即使第二个元素中有测试。如果这是你的要求,好的。但是如果没有,我建议您通过@Thankyou的答案可以学到很多。是的,它符合我们的要求。谢谢你的反馈。为了学习的目的,我可以改进它以适应这种情况。请问谁是@Thankyu?用户写了,并写了一些我在StackOverflow上看到的最鼓舞人心和信息丰富的答案。