Javascript 如何只保留匹配特定条件的数组项?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27131984/
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 can I only keep items of an array that match a certain condition?
提问by Scimonster
I have an array, and I want to filter it to only include items which match a certain condition. Can this be done in JavaScript?
我有一个数组,我想过滤它以只包含匹配特定条件的项目。这可以在 JavaScript 中完成吗?
Some examples:
一些例子:
[1, 2, 3, 4, 5, 6, 7, 8] // I only want [2, 4, 6, 8], i.e. the even numbers
["This", "is", "an", "array", "with", "several", "strings", "making", "up", "a", "sentence."] // I only want words with 2 or fewer letters: ["is", "an", "up", "a"]
[true, false, 4, 0, "abc", "", "0"] // Only keep truthy values: [true, 4, "abc", "0"]
回答by Scimonster
For this, you can use the Array#filter()method, introduced in ECMAScript5. It is supported in all browsers, except for IE8 and lower, and ancient versions of Firefox. If, for whatever reason, you need to support those browsers, you can use a polyfillfor the method.
为此,您可以使用Array#filter()ECMAScript5 中引入的方法。所有浏览器都支持它,除了 IE8 及更低版本,以及旧版本的 Firefox。如果出于某种原因,您需要支持这些浏览器,则可以为该方法使用polyfill。
filter()takes a function as its first argument. For every item of the array, your function is passed three arguments - the value of the current item, its index in the array, and the array itself. If your function returns true(or a truthy value, e.g. 1, "pizza", or 42), that item will be included in the result. Otherwise, it won't. filter()returns a newarray - your original array will be left unmodified. That means that you'll need to save the value somewhere, or it'll be lost.
filter()接受一个函数作为它的第一个参数。对于数组中的每一项,你的函数都会被传递三个参数——当前项的值、它在数组中的索引以及数组本身。如果您的函数返回true(或真值,例如1、"pizza"、 或42),则该项目将包含在结果中。否则,它不会。filter()返回一个新数组 - 您的原始数组将保持不变。这意味着您需要将值保存在某处,否则它将丢失。
Now, in the examples from the question:
现在,在问题的示例中:
var myNumbersArray = [1, 2, 3, 4, 5, 6, 7, 8];
console.log(myNumbersArray.filter(function(num){
return !(num % 2); // keep numbers divisible by 2
}));
console.log(myNumbersArray); // see - it hasn't changed!
var myStringArray = ["This", "is", "an", "array", "with", "several", "strings", "making", "up", "a", "sentence."];
console.log(myStringArray.filter(function(str){
return str.length < 3; // keep strings with length < 3
}));
console.log(myStringArray);
var myBoolArray = [true, false, 4, 0, "abc", "", "0"];
console.log(myBoolArray.filter(Boolean));
// wow, look at that trick!
console.log(myBoolArray);
And for completeness, an example that also uses the index and array parameters: Removing duplicates from the array:
为了完整起见,还有一个使用索引和数组参数的示例:从数组中删除重复项:
var myArray = [1,1,2,3,4,5,6,1,2,8,2,5,2,52,48,123,43,52];
console.log(myArray.filter(function(value, index, array) {
return array.indexOf(value) === index;
}));
回答by Madara's Ghost
To filter entries which aren't strictly arrays, and thus don't have the .filterproperty on their prototype, but are still iterable (like document.getElementsByTagName), you can use
要过滤不是严格数组的条目,因此.filter在其原型上没有属性,但仍可迭代(如document.getElementsByTagName),您可以使用
Array.prototype.filter.call(collection, function filterFunction(el, index, collection) {
...
});
Or the shorthand
或者简写
[].filter.call(collection, function filterFunction(el, index, collection) {
...
});
As for objects which are not iterable, but you still want to filter properties and get an array of keys that pass filtering, you can combine with Object.keyslike so:
对于不可迭代的对象,但您仍然希望过滤属性并获取通过过滤的键数组,您可以Object.keys像这样组合:
var obj = { one: 1, two: 2, three: 3, four: 4 };
var filtered = Object.keys(obj).filter(function(key) {
return obj[key] % 2 === 0;
}); //filtered == ['two', 'four']
Then, you can create a new object containing those properties:
然后,您可以创建一个包含这些属性的新对象:
var filteredObj = filtered.reduce(function(newObj, currentKey) {
newObj[currentKey] = obj[currentKey]; //Add the original value to the new object
return newObj; //Return the new object to continue iteration
}, {}) // Begin iteration with a blank object
//filteredObj is now { two: 2, four: 4 }
The above can even be combined into a function!
以上甚至可以组合成一个函数!
function filterObject(obj, testCallback) {
return Object.keys(obj).filter(function(key, index, array) {
return testCallback(obj[key], index, array); //Call original filter but pass the property
}).reduce(function(newObj, currentKey) {
newObj[currentKey] = obj[currentKey]; //Add the original value to the new object
return newObj; //Return the new object to continue iteration
}, {}); // Begin iteration with a blank object
}
And use like this:
并像这样使用:
var obj = { one: 1, two: 2, three: 3, four: 4 };
var filteredObj = filterObject(obj, function(el) { return el % 2 === 0 });
回答by dinigo
A more concise answer following the one from @Scimonster, using ES6 syntax, would be:
遵循@Scimonster 的更简洁的答案,使用 ES6 语法,将是:
// even numbers
const even = [1, 2, 3, 4, 5, 6, 7, 8].filter(n => n%2 == 0);
// words with 2 or fewer letters
const words = ["This", "is", "an", "array", "with", "several", "strings", "making", "up", "a", "sentence."].filter(el => el.length <= 2);
// truable elements
const trues = [true, false, 4, 0, "abc", "", "0"].filter(v => v);
console.log(even);
console.log(words);
console.log(trues);

