按多个属性和值过滤对象数组

26

如何同时使用多个值过滤对象数组?

例如,在下面的示例中,我可以同时按term_ids 5和6和类型car进行过滤吗?

[  
   {  
      "id":1,
      "term_id":5,
      "type":"car"
   },
   {  
      "id":2,
      "term_id":3,
      "type":"bike"
   },
   {  
      "id":3,
      "term_id":6,
      "type":"car"
   }
]

如果使用库可以使事情更容易,我绝对支持使用。

5个回答

44

你可以使用Array.filter来完成。

var data = [{
    "id": 1,
    "term_id": 5,
    "type": "car"
  },
  {
    "id": 2,
    "term_id": 3,
    "type": "bike"
  },
  {
    "id": 3,
    "term_id": 6,
    "type": "car"
  }
];

var result = data.filter(function(v, i) {
  return ((v["term_id"] == 5 || v["term_id"] == 6) && v.type == "car");
})

console.log(result)


16

下面的函数将会帮助您。

    nestedFilter = (targetArray, filters) => {
          var filterKeys = Object.keys(filters);
          return targetArray.filter(function (eachObj) {
            return filterKeys.every(function (eachKey) {
              if (!filters[eachKey].length) {
                return true; 
              }
              return filters[eachKey].includes(eachObj[eachKey]);
           });
       });
    };

使用以下描述的过滤器来使用此函数:

var filters = {
    "id": ["3"],
    "term_id": ["6"],
    "type": ["car","bike"]
}

不要传递空数组。如果数组中没有任何值,则在筛选器中跳过该属性。

结果将是已过滤的数组。


如果我们可以通过将所有输入值转换为小写来避免大小写敏感匹配,那会怎样呢?类似于 filters[eachKey.toLowerCase()] 和其他类似的方法吗? - program_bumble_bee

15

您可以使用纯JS filter() 方法,并使用 && 来测试两个条件。

var data = [{"id":1,"term_id":5,"type":"car"},{"id":2,"term_id":3,"type":"bike"},{"id":3,"term_id":6,"type":"car"}];

var result = data.filter(function(e) {
  return [5, 6].includes(e.term_id) && e.type == 'car'
});

console.log(result);


太好了!我一直在尝试筛选,但不知道可以像这样做!谢谢你! - BarryWalsh
@Nenad Vracar,非常好!是否可以在不通过对象循环的情况下替换搜索词?我想要突出显示结果。 - Marcoscdoni

0

另一种方法是使用 lodash 的 filter + reduce。

const arr = [{"id":1,"term_id":5,"type":"car"},{"id":2,"term_id":3,"type":"bike"},{"id":3,"term_id":6,"type":"car"}];

const result = [
  {term_id: 5, type: 'car'},
  {term_id: 6, type: 'car'},
].reduce((prev, orCondition) => prev.concat(_.filter(arr, orCondition)), []);

console.log(result);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>


0
我刚刚不得不这样做,看起来以下内容应该有效:
let termFilter = [5,6]
let typeFilter = ['car']
let result = data.filter(({type,term_id}) => termFilter.includes(term_id) && typeFilter.includes(type))

我添加了数组来规范代码,使其更易扩展和更易读一些。
如果条件保证永远不会改变,那么你可以用一行代码来完成。
let result = data.filter(({type,term_id}) => [5,6].includes(term_id) && type == 'car')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接