javascript过滤器数组的多个条件

时间:2015-08-05 11:47:42

标签: javascript arrays filter

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

var users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
    },
    {
        name: 'Tom',
        email: 'tom@mail.com',
        age: 35,
        address: 'England'
    },
    {
        name: 'Mark',
        email: 'mark@mail.com',
        age: 28,
        address: 'England'
}];

并过滤对象:

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

例如,我需要按地址和名称过滤所有用户,因此我会遍历过滤器对象属性并检查出来:

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;
}

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

我有一个小小的想法,为什么它会发生,但仍然坚持它,无法找到一个很好的解决方案来解决它。任何帮助都很明显。感谢。

22 个答案:

答案 0 :(得分:50)

你可以这样做

&#13;
&#13;
var filter = {
  address: 'England',
  name: 'Mark'
};
var users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: 'tom@mail.com',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: 'mark@mail.com',
    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)
&#13;
&#13;
&#13;

答案 1 :(得分:15)

  

对于那些喜欢简洁代码的人来说,另一种看法。

注意 FILTER 方法可以使用额外的参数,然后使用E6箭头函数我们可以重复使用正确的这个得到一个漂亮的单行。

&#13;
&#13;
var users = [{name: 'John',email: 'johnson@mail.com',age: 25,address: 'USA'},
             {name: 'Tom',email: 'tom@mail.com',age: 35,address: 'England'},
             {name: 'Mark',email: 'mark@mail.com',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);
&#13;
<div id="result"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:9)

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

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

答案 3 :(得分:6)

也可以这样做:

    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);
            })

答案 4 :(得分:5)

这是在过滤器中使用箭头功能的ES6版本。之所以将其发布为答案是因为我们大多数人现在都在使用ES6,这可能会帮助读者使用箭头功能let和const以高级方式进行过滤。

const filter = {
  address: 'England',
  name: 'Mark'
};
let users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: 'tom@mail.com',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: 'mark@mail.com',
    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)

答案 5 :(得分:2)

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

&#13;
&#13;
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);
  
&#13;
&#13;
&#13;

答案 6 :(得分:1)

在lodash中,

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

在es6中,

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

答案 7 :(得分:1)

我的解决方案,基于 NIKHIL C M 解决方案:

 let data = [
    { 
      key1: "valueA1", 
      key2: "valueA2",
      key3: []
    },{
      key1: "valueB1", 
      key2: "valueB2"
      key3: ["valuesB3"]
    }
 ];

 let filters = {
    key1: "valueB1",
    key2: "valueB2"
 };

 let filteredData = data.filter((item) => {
     return Object.entries(filters).every(([filter, value]) => {
          return item[filter] === value;
          //Here i am applying a bit more logic like 
          //return item[filter].includes(value) 
          //or filter with not exactly same key name like
          //return !isEmpty(item.key3)
     });
 });

答案 8 :(得分:1)

具有 AND 条件的动态过滤器

过滤掉性别 = 'm' 的人

var people = [
    {
        name: 'john',
        age: 10,
        gender: 'm'
    },
    {
        name: 'joseph',
        age: 12,
        gender: 'm'
    },
    {
        name: 'annie',
        age: 8,
        gender: 'f'
    }
]
var filters = {
    gender: 'm'
}

var out = people.filter(person => {
    return Object.keys(filters).every(filter => {
        return filters[filter] === person[filter]
    });
})


console.log(out)

过滤掉性别 = 'm' 和姓名 = 'joseph' 的人

var people = [
    {
        name: 'john',
        age: 10,
        gender: 'm'
    },
    {
        name: 'joseph',
        age: 12,
        gender: 'm'
    },
    {
        name: 'annie',
        age: 8,
        gender: 'f'
    }
]
var filters = {
    gender: 'm',
    name: 'joseph'
}

var out = people.filter(person => {
    return Object.keys(filters).every(filter => {
        return filters[filter] === person[filter]
    });
})


console.log(out)

您可以提供任意数量的过滤器。

答案 9 :(得分:0)

Array.Filter()Arrow Functions结合使用,我们可以使用

  

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

这是完整的代码段

// initializing list of users
var users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: 'tom@mail.com',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: 'mark@mail.com',
    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);

答案 10 :(得分:0)

由一些小助手组成:

V(/* some arguments */) : b(x.data(),y.data(),x.size()){
    //populate x and y
    b=barycentric_rational<double>(x.data(),y.data(),x.size());
}

答案 11 :(得分:0)

这是一个易于理解的功能解决方案

let filtersObject = {
  address: "England",
  name: "Mark"
};

let users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: 'tom@mail.com',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: 'mark@mail.com',
    age: 28,
    address: 'England'
  }
];

function filterUsers(users, filtersObject) {
  //Loop through all key-value pairs in filtersObject
  Object.keys(filtersObject).forEach(function(key) {
    //Loop through users array checking each userObject
    users = users.filter(function(userObject) {
      //If userObject's key:value is same as filtersObject's key:value, they stay in users array
      return userObject[key] === filtersObject[key]
    })
  });
  return users;
}

//ES6
function filterUsersES(users, filtersObject) {
  for (let key in filtersObject) {
    users = users.filter((userObject) => userObject[key] === filtersObject[key]);
  }
  return users;
}

console.log(filterUsers(users, filtersObject));
console.log(filterUsersES(users, filtersObject));

答案 12 :(得分:0)

这是我发现的另一种方法,其中filterUsers是一个返回用户排序列表的函数。

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

filteredUsers() {
  return this.users.filter((element) => {
    return element['address'].toLowerCase().match(this.filtersample['address'].toLowerCase()) || element['name'].toLowerCase().match(this.filtersample['name'].toLowerCase());
  })
}

答案 13 :(得分:0)

const users = [{
    name: 'John',
    email: 'johnson@mail.com',
    age: 25,
    address: 'USA'
  },
  {
    name: 'Tom',
    email: 'tom@mail.com',
    age: 35,
    address: 'England'
  },
  {
    name: 'Mark',
    email: 'mark@mail.com',
    age: 28,
    address: 'England'
  }
];

const filteredUsers = users.filter(({ name, age }) => name === 'Tom' && age === 35)

console.log(filteredUsers)

答案 14 :(得分:0)

如果将过滤器对象中的值转换为数组,则将具有更大的灵活性:

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

通过这种方式,您可以过滤“英格兰”或“苏格兰”之类的内容,这意味着结果可能包括英格兰和苏格兰的记录:

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

通过该设置,您的过滤功能可以是:

const applyFilter = (data, filter) => data.filter(obj =>
    Object.entries(filter).every(([prop, find]) => find.includes(obj[prop]))
);

// demo
var users = [{name: 'John',email: 'johnson@mail.com',age: 25,address: 'USA'},{name: 'Tom',email: 'tom@mail.com',age: 35,address: 'England'},{name: 'Mark',email: 'mark@mail.com',age: 28,address: 'England'}];var filter = {address: ['England'], name: ['Mark'] };
var filter = {address: ['England'], name: ['Mark'] };

console.log(applyFilter(users, filter));

答案 15 :(得分:0)

如果要在filter中放置多个条件,可以使用&&||运算符。

var product= Object.values(arr_products).filter(x => x.Status==status && x.email==user)

答案 16 :(得分:0)

简洁实用的解决方案

function kangaroo(x1, v1, x2, v2) {

 if (v1 < v2 || (x2 - x1) % (v1 - v2) !== 0) {
  return 'NO';
 } else {
  return 'YES';
 }
};

console.log(kangaroo(x1, v1, x2, v2));

 

然后你就这样使用它:

const combineFilters = (...filters) => (item) => {
    return filters.map((filter) => filter(item)).every((x) => x === true);
};

和 filterFunc1 例如可能看起来像这样:

const filteredArray = arr.filter(combineFilters(filterFunc1, filterFunc2));

答案 17 :(得分:0)

使用 lodash 而不是纯 javascript

这实际上使用 lodash 非常简单,并且非常容易添加/修改过滤器。

import _ from 'lodash';

async getUsersWithFilter(filters) {
     const users = yourArrayOfSomethingReally();

    // Some properties of the 'filters' object can be null or undefined, so create a new object without those undefined properties and filter by those who are defined
    const filtersWithoutUndefinedValuesObject = _.omitBy(
      filters,
      _.isNil,
    );

    return _.filter(users, { ...filtersWithoutUndefinedValuesObject });
}
  1. omitBy 函数检查您的 filters 对象并删除任何为 null 或未定义的值(如果将其删除,lodash.filter 函数不会返回任何结果。

  2. filter 函数将过滤掉所有值与您作为第二个参数传递给函数的对象不匹配的对象(在这种情况下,是您的 >过滤器对象。)

为什么要使用它?

好吧,假设你有这个对象:

const myFiltersObj = {

   name: "Java",
   age: 50

};

如果您想添加另一个过滤器,只需向 myFilterObj 添加一个新属性,如下所示:

const myFiltersObj = {

   name: "Java",
   email: 50,
   country: "HND"

};

调用 getUsersWithFilter 函数,它会正常工作。如果跳过,假设对象中的 name 属性,getUsersWithFilter 函数将按电子邮件和国家/地区过滤就好了。

答案 18 :(得分:0)

功能解决方案

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

这应该可以完成

applyFilters(users, filter);

答案 19 :(得分:0)

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

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

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;
}

答案 20 :(得分:-1)

{
  "college" {
      "id" : "",
      "name" : ""
  }
}

答案 21 :(得分:-2)

arr.filter((item) => {
       if(condition)
       {
         return false;
       }
       return true;
    });