简体   繁体   中英

Filtering an array of objects with javascript

I have a menu array called "items". It has submenus.

I need to filter the items with property "visible" equal 1. I don't know at run time how deep the hierarchy will be. I need a function returning a new array, with the next conditions:

  1. Every non-matching object with no children, or no matches in children hierarchy, should not exist in output object
  2. Every object with a descendant that contains a matching object, should remain
  3. Only descendants with matching objects should remain

My question is similar to this post Recursively filter array of objects .

But it does not work to me. I have used the following function, but it´s not working:

 const items = [ { icon: "mdi-view-dashboard", title: "Dashboard", to: "/", visible: 1, }, { title: "Manutenção", icon: "mdi-hammer-screwdriver", to: "", visible: 1, items: [ { title: "Usuários", icon: "mdi-account", to: "/usuarios", visible: 1, }, { title: "Cores", to: "", visible: 1, items: [ { title: "Cores da Fila", icon: "mdi-eyedropper-variant", to: "/coresfila", visible: 1, }, { title: "Cores da Agenda", icon: "mdi-palette", to: "/coresagenda", visible: 1, }, ], }, { title: "Tabelas Médicas", to: "", visible: 1, items: [ { title: "Convênios", icon: "mdi-clipboard-outline", to: "/convenios", visible: 1, }, { title: "Planos", icon: "mdi-plus-box", to: "/planos", visible: 1, }, { title: "Especialidades", icon: "mdi-format-font", to: "/especialidadescompletas", visible: 1, }, { title: "Modelos de Atestados", icon: "mdi-account-details-outline", to: "/modelosAtestados", visible: 1, }, { title: "Modelos de Prescrições", icon: "mdi-account-edit-outline", to: "/modelosPrescricoes", }, { title: "Cid-10", icon: "mdi-alphabetical", to: "/cid10", visible: 1, }, { title: "Procedimentos", icon: "mdi-alarm-plus", to: "/procedimentos", visible: 1, }, { title: "Materiais", icon: "mdi-table-of-contents", to: "/materiais", visible: 1, }, { title: "Medicamentos", icon: "mdi-water", to: "/medicamentos", visible: 1, }, { title: "Taxas", icon: "mdi-cash-100", to: "/taxas", visible: 1, }, ], }, ], }, { title: "Empresa", icon: "mdi-cash-100", to: "", visible: 1, items: [ { title: "Perfil da Empresa", icon: "mdi-account-network-outline", to: "/perfilempresa", visible: 1, }, { title: "Créditos SMS", icon: "mdi-cash-usd-outline", to: "/creditossms", visible: 1, }, ], }, { title: "Clientes", icon: "mdi-account-alert-outline", to: "/clientes", visible: 1, }, { title: "Agenda", icon: "far fa-calendar-check", to: "/agenda", visible: 1, }, { title: "Fila", icon: "mdi-account-multiple-check", to: "/fila", visible: 1, }, { title: "Atendimento Médico", icon: "fas fa-user-md", to: "/atendimento", visible: 1, }, { title: "Tela de Chamadas", icon: "mdi-play-network-outline", to: "/telao", visible: 1, }, { title: "DICOM", icon: "mdi-radioactive-off", to: "/dicom", visible: 1, }, { title: "Estatísticas", icon: "mdi-chart-box", to: "", visible: 1, items: [ { title: "Clientes", icon: "mdi-account-arrow-right", to: "", visible: 1, items: [ { title: "Por convênios", icon: "mdi-poll", to: "/estat_cliente_por_convenios", visible: 1, }, { title: "Por mês", icon: "mdi-poll", to: "/estat_cliente_por_mes", visible: 1, }, ], }, { title: "Faturamento", icon: "mdi-cash-usd", to: "", visible: 1, items: [ { title: "Por convênios", icon: "mdi-poll", to: "/estat_faturamento_por_convenios", visible: 1, }, { title: "Por mês", icon: "mdi-poll", to: "/estat_faturamento_por_mes", visible: 1, }, ], }, ], }, { title: "Autorizações", icon: "mdi-microphone-variant", to: "/listaautorizacoes", visible: 1, }, { title: "Faturamento", icon: "mdi-cash-usd", to: "", visible: 1, items: [ { title: "Nova Guia", icon: "mdi-cart-plus", to: "/guiasfaturas", visible: 0, }, { title: "Lista Guias", icon: "mdi-tray-plus", to: "/listaguias", visible: 1, }, { title: "Lote de Guias", icon: "mdi-bag-personal", to: "/loteguias", visible: 1, }, ], }, ] function ofilter(arr) { var matches = []; if (!Array.isArray(arr)) return matches; arr.forEach(function(i) { if (i.visible && i.visible === 1) { matches.push(i); } else { let childResults = this.ofilter(i.items); if (childResults.length) matches.push(Object.assign({}, i, { items: childResults })); } }); return matches; } console.log(ofilter(items))

Here's a recursive filter based on a recursive visibility check. This version preserves the nested structure:

 const isVisible = item => item.visible || item.items?.some(isVisible) const filterItems = items => { items.forEach(item => { if (item.items) item.items = filterItems(item.items) }) return items.filter(isVisible) } console.log(filterItems( [ { id: 'a', visible: 1 }, { id: 'b', visible: 0 }, { id: 'c', visible: 0, items: [ { id: 'd', visible: 1 }, { id: 'e', visible: 0 } ] }, { id: 'f', visible: 1, items: [{ id: 'g', visible: 0 }] }, { id: 'h', visible: 0, items: [{ id: 'i', visible: 0 }] }, ] ))

Alternatively, here's a version that returns a flat array:

 const filterItemsFlat = (items, results = []) => { items.forEach(item => { if (item.items) filterItemsFlat(item.items, results) if (item.visible) results.push(item) }) results.forEach(r => delete r.items) return results } console.log(filterItemsFlat( [ { id: 'a', visible: 1 }, { id: 'b', visible: 0 }, { id: 'c', visible: 0, items: [ { id: 'd', visible: 1 }, { id: 'e', visible: 0 } ] }, { id: 'f', visible: 1, items: [{ id: 'g', visible: 0 }] }, { id: 'h', visible: 0, items: [{ id: 'i', visible: 0 }] }, ] ))

Another alternative to question:

 const items = [ 
  { icon: "mdi-view-dashboard", title: "Dashboard", to: "/", visible: 1, }, 
  { title: "Manutenção", icon: "mdi-hammer-screwdriver", to: "", visible: 0, 
   items: [ 
     { title: "Usuários", icon: "mdi-account", to: "/usuarios", visible: 1, }, 
     { title: "Cores", to: "", visible: 0}
   ]
  }
];

function ofilter(arr) {
  let r = [];     
  arr.forEach((i) => {
    if (i.visible == 1) {
      r.push(i);
    } 
    if (i.items) {  
      r.push(ofilter(i.items))
    }    
  })
  return r;
}

console.log('result:', ofilter(items))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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