繁体   English   中英

如何基于内部数组过滤外部数组?

[英]How to filter an outer array based on an inner array?

我有一个像这样的json,我想获取几乎所有具有所选属性等于true的服务的区域。

{
   "areas": [
      {
         "name": "area 1",
         "services": [
            {
               "label": "srv 1",
               "selected": true
            },
            {
               "label": "srv 2",
               "selected": false
            },
            {
               "label": "srv 3",
               "selected": false
            },
            {
               "label": "srv 4",
               "selected": true
            }
         ]
      },
      {
         "name": "area 2",
         "services": [
            {
               "label": "srv 1",
               "selected": false
            },
            {
               "label": "srv 2",
               "selected": true
            },
            {
               "label": "srv 3",
               "selected": false
            },
            {
               "label": "srv 4",
               "selected": false
            }
         ]
      },
      {
         "name": "area 3",
         "services": [
            {
               "label": "srv 1",
               "selected": false
            },
            {
               "label": "srv 2",
               "selected": false
            },
            {
               "label": "srv 3",
               "selected": false
            }
         ]
      },
      {
         "name": "area 4",
         "services": [
            {
               "label": "srv 1",
               "selected": true
            },
            {
               "label": "srv 2",
               "selected": false
            },
            {
               "label": "srv 3",
               "selected": true
            }
         ]
      }
   ]
}

结果必须仅包含具有所选属性等于true的服务的区域,并且必须指出该区域而不更改原始数组。

有了这个代码

const result = areas.filter(area =>
  services.some(srv => srv.selected == true)
);

我获得了所有区域,但是在这些区域内,我具有所有服务(选择为true和选择为false)。

这是我想要的:

{
   "areas": [
      {
         "name": "area 1",
         "services": [
            {
               "label": "srv 1",
               "selected": true
            },
            {
               "label": "srv 4",
               "selected": true
            }
         ]
      },
      {
         "name": "area 2",
         "services": [
            {
               "label": "srv 2",
               "selected": true
            }
         ]
      },
      {
         "name": "area 4",
         "services": [
            {
               "label": "srv 1",
               "selected": true
            },
            {
               "label": "srv 3",
               "selected": true
            }
         ]
      }
   ]
}

谢谢

为避免input.areas原始对象,请map每个input.areas项,以将其变成一个对象,该对象在其services仅包含true selected的,然后根据services属性中是否包含任何项进行filter

 const transform = (input) => input.areas .map(({ name, services }) => ({ name, services: services.filter(({ selected }) => selected) })) .filter(({ services }) => services.length); const input = { "areas": [ { "name": "area 1", "services": [ { "label": "srv 1", "selected": true }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": false }, { "label": "srv 4", "selected": true } ] }, { "name": "area 2", "services": [ { "label": "srv 1", "selected": false }, { "label": "srv 2", "selected": true }, { "label": "srv 3", "selected": false }, { "label": "srv 4", "selected": false } ] }, { "name": "area 3", "services": [ { "label": "srv 1", "selected": false }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": false } ] }, { "name": "area 4", "services": [ { "label": "srv 1", "selected": true }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": true } ] } ] }; console.log(transform(input)); 

您可以减少数组,仅过滤过滤后services包含某些项目的部分。

 var data = { areas: [{ name: "area 1", services: [{ label: "srv 1", selected: true }, { label: "srv 2", selected: false }, { label: "srv 3", selected: false }, { label: "srv 4", selected: true }] }, { name: "area 2", services: [{ label: "srv 1", selected: false }, { label: "srv 2", selected: true }, { label: "srv 3", selected: false }, { label: "srv 4", selected: false }] }, { name: "area 3", services: [{ label: "srv 1", selected: false }, { label: "srv 2", selected: false }, { label: "srv 3", selected: false }] }, { name: "area 4", services: [{ label: "srv 1", selected: true }, { label: "srv 2", selected: false }, { label: "srv 3", selected: true }] }] }, result = data.areas.reduce((r, o) => { var services = o.services.filter(({ selected }) => selected); if (services.length) r.push(Object.assign({}, o, { services })); return r; }, []); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

您可以使用过滤器两次

 const res = data.areas.filter(e => { e.services = e.services.filter(s => s.selected); return e.services.length; }); console.log(res); 
 <script> const data = { "areas": [ { "name": "area 1", "services": [ { "label": "srv 1", "selected": true }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": false }, { "label": "srv 4", "selected": true } ] }, { "name": "area 2", "services": [ { "label": "srv 1", "selected": false }, { "label": "srv 2", "selected": true }, { "label": "srv 3", "selected": false }, { "label": "srv 4", "selected": false } ] }, { "name": "area 3", "services": [ { "label": "srv 1", "selected": false }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": false } ] }, { "name": "area 4", "services": [ { "label": "srv 1", "selected": true }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": true } ] } ] } </script> 

你可以这样做

obj.areas.filter(area =>
  area.services = area.services.filter(srv => srv.selected == true)
);

这应该足够了,您基本上可以使用Array#filter的组合。

 const filterBySelectedServices = list => list .map(area => Object.assign({}, area, { services: area.services.filter(service => service.selected), })) .filter(area => area.services.length); const data = { "areas": [ { "name": "area 1", "services": [ { "label": "srv 1", "selected": true }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": false }, { "label": "srv 4", "selected": true } ] }, { "name": "area 2", "services": [ { "label": "srv 1", "selected": false }, { "label": "srv 2", "selected": true }, { "label": "srv 3", "selected": false }, { "label": "srv 4", "selected": false } ] }, { "name": "area 3", "services": [ { "label": "srv 1", "selected": false }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": false } ] }, { "name": "area 4", "services": [ { "label": "srv 1", "selected": true }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": true } ] } ] }; console.log('result', filterBySelectedServices(data.areas)); 

您可以使用reducefilter并且只接受那些在过滤后服务中包含某些项目的元素

 let data = {"areas": [{"name": "area 1","services": [{"label": "srv 1","selected": true},{"label": "srv 2","selected": false},{"label": "srv 3","selected": false},{"label": "srv 4","selected": true}]},{"name": "area 2","services": [{"label": "srv 1","selected": false},{"label": "srv 2","selected": true},{"label": "srv 3","selected": false},{"label": "srv 4","selected": false}]},{"name": "area 3","services": [{"label": "srv 1","selected": false},{"label": "srv 2","selected": false},{"label": "srv 3","selected": false}]},{"name": "area 4","services": [{"label": "srv 1","selected": true},{"label": "srv 2","selected": false},{"label": "srv 3","selected": true}]}]} let final = data.areas.reduce((op, inp) => { let services = inp.services.filter( ({selected}) => selected ) if(services.length) op.push({...inp, services}) return op },[]) console.log(final) 

您可以使用reduce filter内部数组,而无需更改输入

 const input={"areas":[{"name":"area 1","services":[{"label":"srv 1","selected":true},{"label":"srv 2","selected":false},{"label":"srv 3","selected":false},{"label":"srv 4","selected":true}]},{"name":"area 2","services":[{"label":"srv 1","selected":false},{"label":"srv 2","selected":true},{"label":"srv 3","selected":false},{"label":"srv 4","selected":false}]},{"name":"area 3","services":[{"label":"srv 1","selected":false},{"label":"srv 2","selected":false},{"label":"srv 3","selected":false}]},{"name":"area 4","services":[{"label":"srv 1","selected":true},{"label":"srv 2","selected":false},{"label":"srv 3","selected":true}]}]} const areas = input.areas.reduce((r, a) => { const services = a.services.filter(s => s.selected) if(services.length) r.push({ ...a, services }); return r }, []) console.log({ areas }) 

尝试这样的事情:

 const data = { "areas": [{ "name": "area 1", "services": [{ "label": "srv 1", "selected": true }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": false }, { "label": "srv 4", "selected": true } ] }, { "name": "area 2", "services": [{ "label": "srv 1", "selected": false }, { "label": "srv 2", "selected": true }, { "label": "srv 3", "selected": false }, { "label": "srv 4", "selected": false } ] }, { "name": "area 3", "services": [{ "label": "srv 1", "selected": false }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": false } ] }, { "name": "area 4", "services": [{ "label": "srv 1", "selected": true }, { "label": "srv 2", "selected": false }, { "label": "srv 3", "selected": true } ] } ] } const res = data.areas.map(x => { // Destructure the name and services from the current callback object const { name, services } = x; // Now filter the services object where the .selected property is set to true const filteredServices = services.filter(x => x.selected); if (filteredServices.length) { // Project your desired object return { name: name, services: filteredServices } } }) // Also filter for empty services .filter(x => x); console.log(res); 

您可以在过滤器的回调中进行过滤,如下所示:

 let data = {"areas": [{"name": "area 1", "services": [{"label": "srv 1", "selected": true}, {"label": "srv 2", "selected": false}, {"label": "srv 3", "selected": false}, {"label": "srv 4", "selected": true}]}, {"name": "area 2", "services": [{"label": "srv 1", "selected": false}, {"label": "srv 2", "selected": true}, {"label": "srv 3", "selected": false}, {"label": "srv 4", "selected": false}]}, {"name": "area 3", "services": [{"label": "srv 1", "selected": false}, {"label": "srv 2", "selected": false}, {"label": "srv 3", "selected": false}]}, {"name": "area 4", "services": [{"label": "srv 1", "selected": true}, {"label": "srv 2", "selected": false}, {"label": "srv 3", "selected": true}]}]}; const result = data.areas.filter(area => { // filter area services let selectedServices = area.services.filter(service => { return service.selected; }); // If the area has selected services if (selectedServices.length) { // Save the selected services to area.services area.services = selectedServices; return true; } else { // Do not select the area return false; } }); console.log(result); 

但是,正如@CodeManiac指出的那样,这将使原始数组发生突变,如果要保留它,则使用reducedata.areas.reduce()而不是data.areas.filter()

在完成第一次过滤之后,可以按以下步骤过滤每个索引中的服务:

result.forEach((item)=>{
     item.services = item.services.filter((service)=>service.selected==true);
})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM