2014-11-25 5 views
7

Ho una matrice e voglio filtrarla per includere solo gli elementi che corrispondono a una determinata condizione. Questo può essere fatto in JavaScript?Come posso conservare solo gli elementi di una matrice che corrispondono a una determinata condizione?

Alcuni esempi:

[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"] 
+6

Questo è inteso come una domanda canonica per chiudere gli altri come duplicati di. – Scimonster

risposta

15

Per questo, è possibile utilizzare il metodo Array#filter(), introdotto nel ECMAScript5. È supportato in tutti i browser, tranne IE8 e versioni precedenti e versioni precedenti di Firefox. Se, per qualsiasi motivo, è necessario supportare tali browser, è possibile utilizzare uno polyfill per il metodo.

filter() accetta una funzione come primo argomento. Per ogni elemento dell'array, alla funzione vengono passati tre argomenti: il valore dell'elemento corrente, il suo indice nell'array e l'array stesso. Se la tua funzione restituisce true (o un valore di verità, ad esempio 1, "pizza" o 42), quell'elemento verrà incluso nel risultato. Altrimenti, non lo farà. filter() restituisce un nuovo array: l'array originale verrà lasciato inalterato. Ciò significa che dovrai salvare il valore da qualche parte, altrimenti andrà perso.

Ora, negli esempi della domanda:

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

E per completezza, un esempio che utilizza anche i parametri indice e matrice: rimozione duplicati dalla matrice:

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

5

Per filtrare le voci che non sono strettamente array, e quindi non hanno la proprietà .filter il loro prototipo, ma sono ancora iterabile (come document.getElementsByTagName), è possibile utilizzare

Array.prototype.filter.call(collection, function filterFunction(el, index, collection) { 
    ... 
}); 

O la stenografia

[].filter.call(collection, function filterFunction(el, index, collection) { 
    ... 
}); 

per quanto riguarda gli oggetti che non sono iterabile, ma vuoi comunque filtrare le proprietà e ottenere una serie di chiavi che passano il filtro, è possibile combinare con Object.keys come così:

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

Quindi, è possibile creare un nuovo oggetto che contiene le proprietà:

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 } 

Quanto sopra può anche essere combinati in una funzione!

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 
} 

E utilizzare in questo modo:

var obj = { one: 1, two: 2, three: 3, four: 4 }; 
var filteredObj = filterObject(obj, function(el) { return el % 2 === 0 }); 
0

Una risposta più concisa successivo a quello da @Scimonster, utilizzando la sintassi ES6, sarebbe:

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