Javascript 如何根据属性过滤对象数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2722159/
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
How to filter object array based on attributes?
提问by JGreig
I have the following JavaScript array of real estate home objects:
我有以下房地产住宅对象的 JavaScript 数组:
var json = {
'homes': [{
"home_id": "1",
"price": "925",
"sqft": "1100",
"num_of_beds": "2",
"num_of_baths": "2.0",
}, {
"home_id": "2",
"price": "1425",
"sqft": "1900",
"num_of_beds": "4",
"num_of_baths": "2.5",
},
// ... (more homes) ...
]
}
var xmlhttp = eval('(' + json + ')');
homes = xmlhttp.homes;
What I would like to do is be able to perform a filter on the object to return a subset of "home" objects.
我想要做的是能够对对象执行过滤器以返回“home”对象的子集。
For example, I want to be able to filter based on: price, sqft, num_of_beds, and num_of_baths.
例如,我想根据能够过滤:price,sqft,num_of_beds,和num_of_baths。
How can I perform something in JavaScript like the pseudo-code below:
我如何在 JavaScript 中执行类似下面的伪代码的操作:
var newArray = homes.filter(
price <= 1000 &
sqft >= 500 &
num_of_beds >=2 &
num_of_baths >= 2.5 );
Note, the syntax does not have to be exactly like above. This is just an example.
请注意,语法不必与上述完全相同。这只是一个例子。
回答by CMS
You can use the Array.prototype.filtermethod:
您可以使用以下Array.prototype.filter方法:
var newArray = homes.filter(function (el) {
return el.price <= 1000 &&
el.sqft >= 500 &&
el.num_of_beds >=2 &&
el.num_of_baths >= 2.5;
});
Live Example:
现场示例:
var obj = {
'homes': [{
"home_id": "1",
"price": "925",
"sqft": "1100",
"num_of_beds": "2",
"num_of_baths": "2.0",
}, {
"home_id": "2",
"price": "1425",
"sqft": "1900",
"num_of_beds": "4",
"num_of_baths": "2.5",
},
// ... (more homes) ...
]
};
// (Note that because `price` and such are given as strings in your object,
// the below relies on the fact that <= and >= with a string and number
// will coerce the string to a number before comparing.)
var newArray = obj.homes.filter(function (el) {
return el.price <= 1000 &&
el.sqft >= 500 &&
el.num_of_beds >= 2 &&
el.num_of_baths >= 1.5; // Changed this so a home would match
});
console.log(newArray);
This method is part of the new ECMAScript 5th Editionstandard, and can be found on almost all modern browsers.
这种方法是新的ECMAScript 第 5 版标准的一部分,几乎可以在所有现代浏览器上找到。
For IE, you can include the following method for compatibility:
对于 IE,您可以包含以下兼容性方法:
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun /*, thisp*/) {
var len = this.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) {
var val = this[i];
if (fun.call(thisp, val, i, this))
res.push(val);
}
}
return res;
};
}
回答by Rutesh Makhijani
You can try using framework like jLinq - following is a code sample of using jLinq
您可以尝试使用 jLinq 之类的框架 - 以下是使用 jLinq 的代码示例
var results = jLinq.from(data.users)
.startsWith("first", "a")
.orEndsWith("y")
.orderBy("admin", "age")
.select();
For more information you can follow the link http://www.hugoware.net/projects/jlinq
有关更多信息,您可以点击链接http://www.hugoware.net/projects/jlinq
回答by JuliaCesar
I prefer the Underscore framework. It suggests many useful operations with objects. Your task:
我更喜欢 Underscore 框架。它建议对对象进行许多有用的操作。你的任务:
var newArray = homes.filter(
price <= 1000 &
sqft >= 500 &
num_of_beds >=2 &
num_of_baths >= 2.5);
can be overwriten like:
可以像这样覆盖:
var newArray = _.filter (homes, function(home) {
return home.price<=1000 && sqft>=500 && num_of_beds>=2 && num_of_baths>=2.5;
});
Hope it will be useful for you!
希望对你有用!
回答by Chetan Sandeep Renu
here is the working fiddle which works fine in IE8 using jquery MAP function
这是使用 jquery MAP 功能在 IE8 中工作正常的工作小提琴
http://jsfiddle.net/533135/Cj4j7/
http://jsfiddle.net/533135/Cj4j7/
json.HOMES = $.map(json.HOMES, function(val, key) {
if (Number(val.price) <= 1000
&& Number(val.sqft) >= 500
&& Number(val.num_of_beds) >=2
&& Number(val.num_of_baths ) >= 2.5)
return val;
});
回答by Lou Bagel
I'm surprised no one has posted the one-line response:
我很惊讶没有人发布单行回复:
const filteredHomes = json.homes.filter(x => x.price <= 1000 && x.sqft >= 500 && x.num_of_beds >=2 && x.num_of_baths >= 2.5);
...and just so you can read it easier:
...只是为了让您可以更轻松地阅读:
const filteredHomes = json.homes.filter( x =>
x.price <= 1000 &&
x.sqft >= 500 &&
x.num_of_beds >=2 &&
x.num_of_baths >= 2.5
);
回答by Tejs
You could do this pretty easily - there are probably many implementations you can choose from, but this is my basic idea (and there is probably some format where you can iterate over an object with jQuery, I just cant think of it right now):
你可以很容易地做到这一点 - 可能有很多实现你可以选择,但这是我的基本想法(并且可能有一些格式可以让你用 jQuery 迭代一个对象,我现在想不出来):
function filter(collection, predicate)
{
var result = new Array();
var length = collection.length;
for(var j = 0; j < length; j++)
{
if(predicate(collection[j]) == true)
{
result.push(collection[j]);
}
}
return result;
}
And then you could invoke this function like so:
然后你可以像这样调用这个函数:
filter(json, function(element)
{
if(element.price <= 1000 && element.sqft >= 500 && element.num_of_beds > 2 && element.num_of_baths > 2.5)
return true;
return false;
});
This way, you can invoke the filter based on whatever predicate you define, or even filter multiple times using smaller filters.
这样,您可以根据您定义的任何谓词调用过滤器,甚至可以使用较小的过滤器进行多次过滤。
回答by Akira Yamamoto
You can use jQuery.grep() since jQuery 1.0:
从 jQuery 1.0 开始,您可以使用 jQuery.grep():
$.grep(homes, function (h) {
return h.price <= 1000
&& h.sqft >= 500
&& h.num_of_beds >= 2
&& h.num_of_baths >= 2.5
});
回答by user4620852
You can implement a filter method yourself that meets your needs, here is how:
您可以自己实现满足您需求的过滤器方法,方法如下:
function myfilter(array, test){
var passedTest =[];
for (var i = 0; i < array.length; i++) {
if(test( array[i]))
passedTest.push(array[i]);
}
return passedTest;
}
var passedHomes = myfilter(homes,function(currentHome){
return ((currentHome.price <= 1000 )&& (currentHome.sqft >= 500 )&&(currentHome.num_of_beds >=2 )&&(currentHome.num_of_baths >= 2.5));
});
Hope, it helps!
希望能帮助到你!
回答by Eric
You should check out OGX.Listwhich has built in filtering methods and extends the standard javascript array (and also grouping, sorting and finding). Here's a list of operators it supports for the filters:
您应该查看OGX.List,它内置了过滤方法并扩展了标准的 javascript 数组(以及分组、排序和查找)。这是它为过滤器支持的运算符列表:
'eq' //Equal to
'eqjson' //For deep objects, JSON comparison, equal to
'neq' //Not equal to
'in' //Contains
'nin' //Doesn't contain
'lt' //Lesser than
'lte' //Lesser or equal to
'gt' //Greater than
'gte' //Greater or equal to
'btw' //Between, expects value to be array [_from_, _to_]
'substr' //Substring mode, equal to, expects value to be array [_from_, _to_, _niddle_]
'regex' //Regex match
You can use it this way
你可以这样使用
let list = new OGX.List(your_array);
list.addFilter('price', 'btw', 100, 500);
list.addFilter('sqft', 'gte', 500);
let filtered_list = list.filter();
Or even this way
甚至这样
let list = new OGX.List(your_array);
let filtered_list = list.get({price:{btw:[100,500]}, sqft:{gte:500}});
Or as a one liner
或作为单衬
let filtered_list = new OGX.List(your_array).get({price:{btw:[100,500]}, sqft:{gte:500}});
回答by JohnPan
I use my ruleOutfunction for filtering objects based on specific unwanted property values.I understand that in your example you would like to use conditions instead of values, but my answer is valid for the question title, so I'd like to leave my method here.
我使用我的ruleOut函数根据特定的不需要的属性值过滤对象。我知道在你的例子中你想使用条件而不是值,但我的回答对问题标题有效,所以我想在这里留下我的方法。
function ruleOut(arr, filterObj, applyAllFilters=true) {
return arr.filter( row => {
for (var field in filterObj) {
var val = row[field];
if (val) {
if (applyAllFilters && filterObj[field].indexOf(val) > -1) return false;
else if (!applyAllFilters) {
return filterObj[field].filter(function(filterValue){
return (val.indexOf(filterValue)>-1);
}).length == 0;
}
}
}
return true;
});
}
Say you have a list of actors like this:
假设你有一个这样的演员列表:
let actors = [
{userName:"Mary", job:"star", language:"Turkish"},
{userName:"John", job:"actor", language:"Turkish"},
{userName:"Takis", job:"star", language:"Greek"},
{userName:"Joe", job:"star", language:"Turkish"},
{userName:"Bill", job:"star", language:"Turkish"}
];
and you would like to find all actors that are rated as Holywood stars, their nationality should not be one of 'English', 'Italian', 'Spanish', 'Greek', plus their name would not be one of 'Mary', 'Joe'. Bizzar example, I know! Anyway, with that set of conditions you would create the following object:
并且你想找到所有被评为好莱坞明星的演员,他们的国籍不应该是“English”、“Italian”、“Spanish”、“Greek”之一,而且他们的名字也不应该是“Mary”之一, '乔'。比萨的例子,我知道!无论如何,在这组条件下,您将创建以下对象:
let unwantedFieldsFilter= {
userName: ['Mary', 'Joe'],
job: ['actor'],
language: ['English', 'Italian', 'Spanish', 'Greek']
};
OK, now if you ruleOut(actors, unwantedFieldsFilter)you would only get
好的,现在如果你ruleOut(actors, unwantedFieldsFilter)只得到
[{userName: "Bill", job: "star", language: "Turkish"}]
[{用户名:“比尔”,工作:“明星”,语言:“土耳其语”}]
And Bill is your man, since his name is not one of 'Mary', 'Joe', his nationality is not included in ['English', 'Italian', 'Spanish', 'Greek'] plus he is a Star!
比尔是你的男人,因为他的名字不是“玛丽”、“乔”中的一个,他的国籍不包括在[“英语”、“意大利”、“西班牙语”、“希腊”]中,而且他是明星!
There is one option in my method, that is applyAllFiltersand is true by default.
If you would try to ruleOut with this param set as false, that would work as an 'OR' filtering instead of 'AND'.
Example: ruleOut(actors, {job:["actor"], language:["Italian"]}, false)would get you everyone that is not an actor or Italian:
我的方法中有一个选项,即applyAllFilters默认情况下为 true。如果您尝试将此参数设置为 false 来排除,这将用作“OR”过滤而不是“AND”。示例:ruleOut(actors, {job:["actor"], language:["Italian"]}, false)会让你所有不是演员或意大利人的人:
[{userName: "Mary", job: "star", language: "Turkish"},
{userName: "Takis", job: "star", language: "Greek"},
{userName: "Joe", job: "star", language: "Turkish"},
{userName: "Bill", job: "star", language: "Turkish"}]
[{userName: "Mary", job: "star", language: "Turkish"},
{userName: "Takis", job: "star", language: "Greek"},
{userName: "Joe", job: “明星”,语言:“土耳其语”},
{用户名:“比尔”,工作:“明星”,语言:“土耳其语”}]

