How can I only keep items of an array that match a certain condition?

前端 未结 3 1754
轻奢々
轻奢々 2020-11-27 21:25

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?

Some examples:

[1, 2,         


        
相关标签:
3条回答
  • 2020-11-27 21:44

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

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

    0 讨论(0)
  • 2020-11-27 21:54

    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.

    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.

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

    0 讨论(0)
  • 2020-11-27 21:57

    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

    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:

    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 });
    
    0 讨论(0)
提交回复
热议问题