【问题标题】:filter nested array of objects based on object values Javascript ES6根据对象值过滤嵌套的对象数组Javascript ES6
【发布时间】:2019-09-19 17:04:49
【问题描述】:

我正在尝试针对 search 变量(它是一个字符串)过滤下面的对象数组。因此,用户可以根据标题、年份或人名进行搜索

array = [{
    "title": "Test",
    "year": 2018,
    "people": [
      {
        "name": "person1"
      },
      {
        "name": "person2"
      }],
  },
  {
    "title": "Test2",
    "year": 2018,
    "people": [
      {
        "name": "person3"
      },
      {
        "name": "person4"
      },
      {
        "name": "person5"
      }],
   },...]

我已经编写了下面的函数,它适用于 titleyear 但我不知道如何搜索里面的 people 数组功能。我知道如何在没有 ES6 的情况下做到这一点,但我更喜欢 ES6,这仍然让我感到困惑:

filteredArray() {
            let search = this.search.toLowerCase();
            return this.array.filter(function (item) {
                    return Object.values(item).some(val =>
                        String(val).toLowerCase().includes(search));
            })
        },

this.searchv-model,用于保存用户输入的值。 这是Codepen

感谢您的帮助:)

【问题讨论】:

    标签: javascript vue.js ecmascript-6 filter


    【解决方案1】:

    以下代码有助于您的用例

       var searchString = 'person5';
    
       let result = array.filter(ele => 
        ele.title.includes(searchString)
        || `${ele.year}`.includes(searchString)
        || ele.people.some(pele => pele.name.includes(searchString))
       )
       console.log(JSON.stringify(result));
    

    【讨论】:

    • 为什么使用.filter(...).length > 0 而不是.some(...)
    • @Barmer 是的,那更好,使用.some()更新答案
    • 感谢@karthikdivi 的回复。它适用于一年,但不适用于标题和人员。
    • @DjSh 三种情况我都测试过了,你可以跑这里看看onecompiler.com/javascript/3v2t9b96g
    • 我刚刚在您的示例上运行了它,这是people: [ [Object], [Object], [Object] ] 的结果,表明它不起作用
    【解决方案2】:

    创建一个搜索字符串的映射/散列以轻松搜索:

    const array = [{
    "title": "Test",
    "year": 2018,
    "people": [
      {
        "name": "person1"
      },
      {
        "name": "person2"
      }],
      },
      {
    "title": "Test2",
    "year": 2018,
    "people": [
      {
        "name": "person3"
      },
      {
        "name": "person4"
      },
      {
        "name": "person5"
      }],
       }];
    
    
    let map = array.reduce((map,item,i)=>{
      let values = Object.values(item);
      let persons = values.pop().map(e=>e.name);
      [...values,...persons].forEach(e=>map.set(String(e).toLowerCase(),i))
      return map;
    },new Map());
    
    //console.log(...map);
    ['person1','person3','Test2'].forEach(e=>console.log({[e]:array[map.get(String(e).toLowerCase())]}))

    对于 Vue,试试

    filteredArray() {
        let search = this.search.toLowerCase();
        let arr2d = this.arr2d;
        if(typeof arr2d ==="undefined"){
         arr2d = this.array.reduce((arr,item)=>{
          let values = Object.values(item);
          let persons = values.pop().map(e=>e.name);
          arr.push([...values,...persons]);
          return arr;
         },[]);
        }
        return this.array.filter((item,i)=>arr2d[i].some(el=>
            String(el).toLowerCase().includes(search)))
        }
    
    

    【讨论】:

    • 你能帮我理解你的代码吗?我提供了一个codepen。我不明白如何在那里应用它
    • @DjSh 我已经尝试过 vue。基本策略是将对象的主要数组减少为数组数组并将其存储(arr2d)。这个arr2d 将包含相同索引中的字符串列表,例如 [['item','person1','person2',2018],['item2','person3','person4',....]] .这样,您就可以轻松过滤所有内容。
    • 非常感谢您的时间和帮助。我必须修改你的代码才能正常工作。 Codepen。不需要 if 语句(你初始化 arr2d 的方式的 bcs)。
    • @DjSh 我想让arr2d 永久化,而不是在每个搜索类型上计算。按照你初始化它的方式,它会一次又一次地从相同的出版物中计算 arr2d并再次为每个搜索字母。如果可能的话,我希望这部分计算在 filteredArray() 方法之外。它应该只在出版物的新条目上计算。
    猜你喜欢
    • 2020-03-11
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2020-09-17
    • 2022-01-20
    • 1970-01-01
    • 2019-10-15
    相关资源
    最近更新 更多