Javascript javascript过滤数组多个条件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31831651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:14:41  来源:igfitidea点击:

javascript filter array multiple conditions

javascriptarraysfilter

提问by user3673623

I want to simplify an array of objects. Let's assume that I have following array:

我想简化一组对象。让我们假设我有以下数组:

var users = [{
    name: 'John',
    email: '[email protected]',
    age: 25,
    address: 'USA'
    },
    {
        name: 'Tom',
        email: '[email protected]',
        age: 35,
        address: 'England'
    },
    {
        name: 'Mark',
        email: '[email protected]',
        age: 28,
        address: 'England'
}];

And filter object:

和过滤对象:

var filter = {address: 'England', name: 'Mark'};

For example i need to filter all users by address and name, so i do loop through filter object properties and check it out:

例如,我需要按地址和名称过滤所有用户,所以我循环过滤器对象属性并检查它:

function filterUsers (users, filter) {
    var result = [];
    for (var prop in filter) {
        if (filter.hasOwnProperty(prop)) {

            //at the first iteration prop will be address
            for (var i = 0; i < filter.length; i++) {
                if (users[i][prop] === filter[prop]) {
                    result.push(users[i]);
                }
            }
        }
    }
    return result;
}

So during first iteration when prop - addresswill be equal 'England'two users will be added to array result (with name Tom and Mark), but on the second iteration when prop namewill be equal Markonly the last user should be added to array result, but i end up with two elements in array.

因此,在第一次迭代中,何时prop - address将等于'England'两个用户将被添加到数组结果中(名称为 Tom 和 Mark),但在第二次迭代中,何时prop nameMark仅将最后一个用户添加到数组结果中,但我最终得到了两个数组中的元素。

I have got a little idea as why is it happening but still stuck on it and could not find a good solution to fix it. Any help is appreciable. Thanks.

我对它为什么会发生有了一点想法,但仍然坚持下去并且找不到解决它的好方法。任何帮助都是可观的。谢谢。

回答by Raghavendra

You can do like this

你可以这样做

var filter = {
  address: 'England',
  name: 'Mark'
};
var users = [{
    name: 'John',
    email: '[email protected]',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: '[email protected]',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: '[email protected]',
    age: 28,
    address: 'England'
  }
];


users= users.filter(function(item) {
  for (var key in filter) {
    if (item[key] === undefined || item[key] != filter[key])
      return false;
  }
  return true;
});

console.log(users)

回答by SoEzPz

Another take for those of you that enjoy succinct code.

对于那些喜欢简洁代码的人来说,这是另一种选择。

NOTE: The FILTERmethod can take an additional thisargument, then using an E6 arrow function we can reuse the correct thisto get a nice one-liner.

注意FILTER方法可以使用额外的this参数,然后使用 E6 箭头函数我们可以重用正确的this来获得一个不错的单行。

var users = [{name: 'John',email: '[email protected]',age: 25,address: 'USA'},
             {name: 'Tom',email: '[email protected]',age: 35,address: 'England'},
             {name: 'Mark',email: '[email protected]',age: 28,address: 'England'}];

var query = {address: "England", name: "Mark"};

var result = users.filter(search, query);

function search(user){
  return Object.keys(this).every((key) => user[key] === this[key]);
}




// |----------------------- Code for displaying results -----------------|
var element = document.getElementById('result');

function createMarkUp(data){
  Object.keys(query).forEach(function(key){
    var p = document.createElement('p');
    p.appendChild(document.createTextNode(
    key.toUpperCase() + ': ' + result[0][key]));
    element.appendChild(p);
  });
}

createMarkUp(result);
<div id="result"></div>

回答by Abhishek Chandran

You can do this in a line

您可以在一行中执行此操作

users = users.filter(obj => obj.name == filter.name && obj.address == filter.address)

回答by Diogo Rodrigues

Can also be done this way:

也可以这样做:

    this.users = this.users.filter((item) => {
                return (item.name.toString().toLowerCase().indexOf(val.toLowerCase()) > -1 ||
                item.address.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
                item.age.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
                item.email.toLowerCase().indexOf(val.toLowerCase()) > -1);
            })

回答by Hemadri Dasari

Here is ES6 version of using arrow function in filter. Posting this as an answer because most of us are using ES6 these days and may help readers to do filter in advanced way using arrow function, let and const.

这是在过滤器中使用箭头函数的 ES6 版本。将此作为答案发布,因为我们大多数人现在都在使用 ES6,并且可以帮助读者使用箭头函数、let 和 const 以高级方式进行过滤。

const filter = {
  address: 'England',
  name: 'Mark'
};
let users = [{
    name: 'John',
    email: '[email protected]',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: '[email protected]',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: '[email protected]',
    age: 28,
    address: 'England'
  }
];


users= users.filter(item => {
  for (let key in filter) {
    if (item[key] === undefined || item[key] != filter[key])
      return false;
  }
  return true;
});

console.log(users)

回答by Hamza Khanzada

Using Array.Filter()with Arrow Functionswe can achieve this using

使用Array.Filter()箭头函数,我们可以使用

users = users.filter(x => x.name == 'Mark' && x.address == 'England');

users = users.filter(x => x.name == 'Mark' && x.address == 'England');

Here is the complete snippet

这是完整的片段

// initializing list of users
var users = [{
    name: 'John',
    email: '[email protected]',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: '[email protected]',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: '[email protected]',
    age: 28,
    address: 'England'
  }
];

//filtering the users array and saving 
//result back in users variable
users = users.filter(x => x.name == 'Mark' && x.address == 'England');


//logging out the result in console
console.log(users);

回答by Richard Richie

In lodash,

在 lodash 中,

_.filter(users,{address: 'England', name: 'Mark'})

In es6,

在es6中,

users.filter(o => o.address == 'England' && o.name == 'Mark')

回答by Co?kun Deniz

I think this might help.

我认为这可能会有所帮助。

const filters = ['a', 'b'];

const results = [
  {
    name: 'Result 1',
    category: ['a']
  },
  {
    name: 'Result 2',
    category: ['a', 'b']
  },
  {
    name: 'Result 3',
    category: ['c', 'a', 'b', 'd']
  }
];

const filteredResults = results.filter(item =>
  filters
    .map(val => item.category.indexOf(val))
    .map(val => (val > -1 ? true : false))
    .reduce((acc, cum) => acc && cum)
);

console.log(filteredResults);
  

回答by The_Black_Smurf

If the finality of you code is to get the filtered user, I would invert the forto evaluate the userinstead of reducing the result array during each iteration.

如果您的代码最终要获得过滤后的用户,我会反转for来评估user而不是在每次迭代期间减少结果数组。

Here an (untested) example:

这是一个(未经测试的)示例:

function filterUsers (users, filter) {
    var result = [];

    for (i=0;i<users.length;i++){
        for (var prop in filter) {
            if (users.hasOwnProperty(prop) && users[i][prop] === filter[prop]) {
                result.push(users[i]);
            }
        }
    }
    return result;
}

回答by Houssem Zitoun

functional solution

功能解决方案

function applyFilters(data, filters) {
  return data.filter(item =>
    Object.keys(filters)
      .map(keyToFilterOn =>
        item[keyToFilterOn].includes(filters[keyToFilterOn]),
      )
      .reduce((x, y) => x && y, true),
  );
}

this should do the job

这应该可以完成工作

applyFilters(users, filter);

applyFilters(users, filter);