我怎样才能保留符合特定条件的数组项?

时间:2022-04-03 09:02:37

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"]

3 个解决方案

#1


17  

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 polyfill for the method.

为此,您可以使用ECMAScript5中引入的Array#filter()方法。除了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 new array - 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,“披萨”或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;
}));

#2


5  

To filter entries which aren't strictly arrays, and thus don't have the .filter property 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.keys like 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 });

#3


0  

A more concise answer following the one from @Scimonster, using ES6 syntax, would be:

使用ES6语法,来自@Scimonster的一个更简洁的答案是:

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

#1


17  

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 polyfill for the method.

为此,您可以使用ECMAScript5中引入的Array#filter()方法。除了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 new array - 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,“披萨”或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;
}));

#2


5  

To filter entries which aren't strictly arrays, and thus don't have the .filter property 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.keys like 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 });

#3


0  

A more concise answer following the one from @Scimonster, using ES6 syntax, would be:

使用ES6语法,来自@Scimonster的一个更简洁的答案是:

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