如何过滤/搜索多个子数组?

时间:2019-12-18 13:38:56

标签: javascript arrays filter

我正在为具有位置(城市,郊区,街道)的父子结构搜索功能。 我想搜索街道名称并获得结果,但要保留结构。

数组结构如下:

const cities = [
  {
    name: 'city1', sublocations: [
      {
        name: 'suburb1', sublocations: [
          {name: 'street1'},
          {name: 'street2'},
          {name: 'street3'},
        ]
      }, {
        name: 'suburb2', sublocations: [
          {name: 'street1'},
          {name: 'street2'},
          {name: 'street3'},
        ]
      }
    ]
  }
];

例如,当我搜索 street1 时,我想要得到它:

const cities = [
  {
    name: 'city1', sublocations: [
      {
        name: 'suburb1', sublocations: [
          {name: 'street1'},
        ]
      }, {
        name: 'suburb2', sublocations: [
          {name: 'street1'},
        ]
      }
    ]
  }
];

我使用array.filter函数进行了尝试,但是它会覆盖数据,并且当我删除搜索字符串时,数组的其余部分将不会恢复。

2 个答案:

答案 0 :(得分:4)

我认为该代码段应该可以解决问题:

var cities = [
 {name :'city1', sublocations:[
     {name :'suburb1', sublocations:[
         {name :'street1'},
         {name :'street2'}, 
          {name :'street3'}, 
     ]},
     {name :'suburb2', sublocations:[
         {name :'street1'},
         {name :'street2'}, 
         {name :'street3'}, 
     ]}
 ]}
];
let findStreet = function(streetName) {
  return cities.map(city=>
    ({...city, sublocations:city.sublocations.map(suburb=>
      ({...suburb, sublocations:suburb.sublocations.filter(
          street=>street.name===streetName
        )
      })
    )})
  )
}
console.log(findStreet("street1"));

答案 1 :(得分:2)

如果您需要更多灵活性,可以通过添加一个type键来概括位置类型,例如:

{ type: 'city', name: 'city1', locations: [] }

然后使用递归过滤器函数为树中的每个节点做出决策,例如:

const filterTree = (nodes, childrenKey, selector) => {
  return nodes.filter(selector).map(node => {
    return node.hasOwnProperty(childrenKey)
      ? {...node, [childrenKey]: filterTree(node[childrenKey], childrenKey, selector)}
      : node;
  });
};

示例:

const locations = [
  {
    type: 'city', name: 'city1', locations: [
      {
        type: 'suburb', name: 'suburb1', locations: [
          {
            type: 'street',
            name: 'street1'
          },
          {
            type: 'street',
            name: 'street2'
          },
          {
            type: 'street',
            name: 'street3'
          },
        ]
      }, {
        type: 'suburb', name: 'suburb2', locations: [
          {
            type: 'street',
            name: 'street1'
          },
          {
            type: 'street',
            name: 'street2'
          },
          {
            type: 'street',
            name: 'street3'
          },
        ]
      }
    ]
  }
];

const filterTree = (nodes, childrenKey, selector) => {
  return nodes.filter(selector).map(node => {
    return node.hasOwnProperty(childrenKey)
      ? {...node, [childrenKey]: filterTree(node[childrenKey], childrenKey, selector)}
      : node;
  });
};

// example
const filtered = filterTree(locations, 'locations', ({type, name}) => {
  return type === 'city'                           // allow all cities 
      || (type === 'suburb' && name === 'suburb2') // but only specific suburbs
      || (type === 'street' && name === 'street2') // and streets;
});

console.log(filtered);