按键值对过滤数组中的对象

时间:2019-04-03 01:40:44

标签: javascript lodash

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

    [
      {
        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)

4 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,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)

答案 1 :(得分: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 :(得分:0)

您可以创建一个自定义方法,该方法使用成对的(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;}

答案 3 :(得分:0)

用于动态对象过滤器。您可以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))