Javascript 按部分路径过滤对象

Javascript 按部分路径过滤对象,javascript,Javascript,如何过滤给定部分路径的对象 举个例子 let address = { country :{ name:'Japan', city:{ name:'Tokyo', town: { name:'korushawa' } }, code:'JP' }, nearbyCountry:'Korea' } 路径1:countr.cit 对于地址,路径1将导致 { country :{ city:{

如何过滤给定部分路径的对象

举个例子

let address  = {
  country :{
    name:'Japan',
    city:{
      name:'Tokyo',
      town: {
        name:'korushawa'
      }
    },
    code:'JP'
  },
  nearbyCountry:'Korea'
}
路径1:countr.cit

对于
地址
路径1将导致

{
  country :{
    city:{
      name:'Tokyo',
      town: {
        name:'korushawa'
      }
    }
  }
}

路径2:countr

对于路径2, 我应该得到整个
地址
对象,因为countr存在于
国家/地区
近邻国家/地区

{
  country :{
    name:'Japan',
    city:{
      name:'Tokyo',
      town: {
        name:'korushawa'
      }
    }
  },
  nearbyCountry:'Korea'
}
编辑:我已经能够解决这个问题,当给定一个精确的路径时(例如:
country.city
)。但是在部分路径上有困难。

  • 您可以创建一个递归函数,该函数将对象和部分路径数组作为参数
  • 获取最新的部分路径,并过滤该路径所包含的键
  • 如果没有键,则返回null
  • 否则,使用
    reduce
    • 如果没有剩余的键,只需将
      obj
      的所有过滤属性添加到累加器中即可
    • 否则,递归调用函数get另一个嵌套对象
const address={国家:{名称:'Japan',城市:{名称:'Tokyo',城镇:{名称:'korushawa'}},代码:'JP'},邻近国家:'Korea'};
函数过滤器对象(对象、路径){
如果(!obj)返回空值;
const partial=path.shift(),
filteredKeys=Object.keys(obj).filter(k=>k.toLowerCase().includes(部分));
如果(!filteredKeys.length)返回null;//找不到路径为的键
返回filteredKeys.reduce((附件,键)=>{
if(!path.length)返回{…acc[key]:obj[key]}
const nest=filterObject(obj[key],…path])//过滤另一个级别
返回嵌套?{…acc,[键]:nest}:acc
},空)
}
让路;
log(路径='countr',':');
console.log(filterObject(地址、路径、拆分('.'))
log(路径='countr.cit',':');
console.log(filterObject(地址、路径、拆分('.'))
log(路径='countr.cit.to',':';
console.log(filterObject(地址、路径、拆分('.'))
log(路径='countr.cit.doesntexist',':');
console.log(filterObject(地址、路径、拆分('.'))

.as console wrapper{max height:100%!important;top:0;}
由于我不完全理解您的目标(例如:为什么在第一个输出示例中,您保留
country
对象的
name
属性,而不是
code
属性),因此我将给出两种方法,希望能够帮助您

第一种方法: 在第一种方法中,我们递归遍历主对象,过滤掉在特定级别不匹配的
键。输出将是一个
对象
,其属性在特定级别匹配:

let地址={
国家:{
名称:"日本",,
城市:{名称:'东京',城市:{名称:'korushawa'},
代码:“JP”
},
nearbyCountry:{名称:'Korea',代码:'KO'}
};
常量myFilter=(对象,键)=>
{
if(key.length k.toLowerCase().match(key[0])匹配
?({…nObj[k]:myFilter(obj[k],keys.slice(1))})
:nObj,
{}
);
}
常量customFilter=(o,k)=>myFilter(
JSON.parse(JSON.stringify(o)),
k、 拆分(“.”).map(x=>x.toLowerCase())
);
log(“按'countr'过滤:”,customFilter(地址,'countr”);
log(“按'countr.cit'过滤:”,customFilter(地址,“countr.cit”);
log(“按'countr.cit.to':”过滤,customFilter(地址,“countr.cit.to”);
log(“按'countr.cit.lala'过滤:”,customFilter(地址,“countr.cit.lala”)
.as控制台{背景色:黑色!重要;颜色:石灰;}

.as console wrapper{max height:100%!important;top:0;}
此方法依赖于筛选条目并通过映射具有单个属性的对象来重建新对象

函数getParts(对象、片段){
var[part,…rest]=fragments.split('.');
返回Object.assign({},…)对象
.条目(对象)
.filter(([key])=>key.toLowerCase().includes(部分))
.map([k,v])=>{
if(!rest.length)返回{[k]:v};
var parts=v&&typeof=v=='object'&&getParts(v,rest.join('.');
if(parts)返回{[k]:parts};
})
);
}
let address={国家:{名称:'Japan',城市:{名称:'Tokyo',城镇:{名称:'korushawa'}},代码:'JP'},近邻国家:'Korea'};
日志(getParts(地址'countr.cit');
日志(getParts(地址'countr')

。作为控制台包装{max height:100%!important;top:0;}
您可以添加完整路径的解决方案吗?它实际上非常简单。检查此方法的问题是,一次只能在输出中有一个子树。例如:对于路径'country',它不会给出
nearbyCountry:'Korea'
subtree.OP说:“对于路径2,我应该得到整个address对象,因为countr存在于country和nearbyCountry中。
startsWith
也不起作用
includes()
。您需要一个不区分大小写的
RegExp
。谢谢。
([key])=>key.toLowerCase().includes(part)
可以是
([key])=>key.toLowerCase().includes(part.toLowerCase())