【问题标题】:Filter objects in array by key-value pairs按键值对过滤数组中的对象
【发布时间】:2019-04-03 11:13:51
【问题描述】:

我有一个这样的对象数组:

    [
      {
        id: 'a',
        name: 'Alan',
        age: 10
      },
      {
        id: 'ab'
        name: 'alanis',
        age: 15
      },
      {
        id: 'b',
        name: 'Alex',
        age: 13
      }
    ]

我需要传递一个像 { id: 'a', name: 'al' } 这样的对象,以便它执行通配符过滤并返回一个包含前两个对象的数组。

所以,步骤是:

  1. 对于数组中的每个对象,从给定的过滤器对象中过滤相关的键

  2. 对于每个键,检查值是否以匹配过滤器对象键的值开头

目前我正在使用 lodash 的过滤器功能,以便它进行完全匹配,但不是以/通配符类型开头的匹配。这就是我正在做的:

filter(arrayOfObjects, filterObject)

【问题讨论】:

    标签: javascript lodash


    【解决方案1】:

    认为您正在寻找这样的东西?基本上会对过滤器对象中每个键的值进行 string.includes 匹配——如果其中一个键值匹配,那么它将包含在结果中。如果您希望整个过滤器对象匹配,您可以使用 .every 而不是 .some...

    const data = [
      {
        id: 'a',
        name: 'Alan',
        age: 10
      },
      {
        id: 'ab',
        name: 'alanis',
        age: 15
      },
      {
        id: 'b',
        name: 'Alex',
        age: 13
      }
    ]
    
    const filter = { id: 'a', name: 'al' }
    
    function filterByObject(filterObject, data) {
      const matched = data.filter(object => {
        return Object.entries(filterObject).some(([filterKey, filterValue]) => {
          return object[filterKey].includes(filterValue)
        })
      })
      return matched
    }
    
    console.log(filterByObject(filter, data))
    

    【讨论】:

      【解决方案2】:

      如果我正确理解您的问题,startsWith 是您要查找的关键词吗?

      const arr = [
      {
        id: 'a',
        name: 'Alan',
        age: 10
      },
      {
        id: 'ab',
        name: 'alanis',
        age: 15
      },
      {
        id: 'b',
        name: 'Alex',
        age: 13
      }
      ];
      
      const searchTerm = { id: 'a', name: 'al' }
      const result = arr.filter(x => 
                      x.id === searchTerm.id || 
                      x.name.startsWith(searchTerm.name)
                    );
                    
      console.log(result)

      【讨论】:

      • 是的,但是 searchTerm 应该传递一个带有任意键的对象。所以它不会总是 id 和 name。
      【解决方案3】:

      您可以创建一个自定义方法,通过 (key, regular expression)Array.filter() 迭代器内部的 Object.entries() 对来接收和对象,以检查某些匹配项。

      let input = [
        {id: 'a', name: 'Alan', age: 10},
        {id: 'ab', name: 'alanis', age: 15},
        {id: 'b', name: 'Alex', age: 13}
      ];
      
      const filterWithSome = (arr, obj) =>
      {
          return arr.filter(o =>
          {
              return Object.entries(obj).some(([k, v]) => o[k].match(v));
          });
      }
      
      console.log(filterWithSome(input, {id: /^a/, name: /^al/}));
      .as-console {background-color:black !important; color:lime;}
      .as-console-wrapper {max-height:100% !important; top:0;}

      如果您希望对作为参数传递的对象的每个 (key, regular expression) 进行匹配,则可以将 Array.some() 替换为 Array.every()

      let input = [
        {id: 'a', name: 'Alan', age: 10},
        {id: 'ab', name: 'alanis', age: 15},
        {id: 'b', name: 'Alex', age: 13}
      ];
      
      const filterWithEvery = (arr, obj) =>
      {
          return arr.filter(o =>
          {
              return Object.entries(obj).every(([k, v]) => o[k].match(v));
          });
      }
      
      console.log(filterWithEvery(input, {id: /^ab/, name: /^al/}));
      .as-console {background-color:black !important; color:lime;}
      .as-console-wrapper {max-height:100% !important; top:0;}

      【讨论】:

        【解决方案4】:

        用于动态对象过滤器。你可以closurereduce

        const data = [
          {id: 'a',name: 'Alan',age: 10},
          {id: 'ab',name: 'alanis',age: 15},
          {id: 'b',name: 'Alex',age: 13}
        ]
        
        const queryObj = { id: 'a', name: 'al' }
        const queryObj2 = { name: 'al', age: 13 }
        
        const filterWith = obj => e => { 
          return Object.entries(obj).reduce((acc, [key, val]) => {
            if(typeof val === 'string') return acc || e[key].startsWith(val)
            else return acc || e[key] === val
          }, false)
        }
        
        const filter1 = filterWith(queryObj)
        const filter2 = filterWith(queryObj2)
        
        console.log(data.filter(filter1))
        console.log(data.filter(filter2))

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-22
          • 2018-10-20
          • 2022-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多