HOWTO · JavaScript
如何在 JavaScript 中依多個條件篩選陣列
本文將介紹如何在 JavaScript 中使用多個條件篩選陣列,並比較動態條件與固定條件的寫法。
本頁內容
使用 JavaScript 的 filter() 方法搭配判斷式,只在陣列元素符合所有必要條件時回傳 true。如果條件是在執行時才提供,逐一比對指定的屬性和值;如果條件已知,則用 && 串接各項比較。這兩種寫法都會讓 filter() 回傳只包含符合條件元素的新陣列。
在 JavaScript 中過濾多個條件
filter() 會針對陣列中每個已設定的元素呼叫回呼函式,並在回呼結果為真值時保留該元素。它不會把元素改成 true 或 false,也不會改動原始陣列。回呼函式會收到目前元素、索引及原陣列;大多數判斷式只需要使用元素。回傳的是新陣列,但其中符合條件的物件仍與來源陣列中的物件參照相同。
filter(callbackFn)
callbackFn 是判斷式,用來檢查元素並回傳真值或假值。如果沒有任何元素符合條件,回傳的陣列會是空陣列。稀疏陣列中未設定值的空槽會被略過,因為回呼函式不會收到這些索引。如需完整的回呼函式簽章與行為,請參閱 MDN 的 filter() 文件。
使用傳統方法
當條件集合來自表單或其他資料來源時,可以將條件存入物件,再逐一檢查其中的項目。以下範例要求每個指定的鍵都是使用者物件本身的屬性,而且屬性值必須完全相同。給定的條件會選出 Aleena,因為她的姓名與地址都符合。
const criteria = {
address: 'India',
name: 'Aleena'
};
const users = [
{name: 'John Doe', email: 'johndoe@mail.com', age: 25, address: 'USA'},
{name: 'Aleena', email: 'aleena@mail.com', age: 35, address: 'India'},
{name: 'Mark Smith', email: 'marksmith@mail.com', age: 28, address: 'England'}
];
const filteredUsers = users.filter((user) => {
return Object.entries(criteria).every(([key, value]) =>
Object.prototype.hasOwnProperty.call(user, key) && user[key] === value
);
});
console.log(filteredUsers);
[
{
name: 'Aleena',
email: 'aleena@mail.com',
age: 35,
address: 'India'
}
]
Object.entries(criteria) 會提供各組屬性與值,而 every() 會要求每一組都符合。嚴格相等運算子(===)會同時比對值與型別;如果物件缺少指定屬性,就不會符合該條件。若條件物件是空的,every() 對每位使用者都會回傳 true,因此結果會包含所有使用者。這種寫法可配合任意一組鍵,不必為每個欄位另外撰寫比較式。
檢查屬性是否為物件本身所有,也能避免繼承而來的屬性被誤認為符合指定鍵。若資料位於巢狀物件中,請明確比對巢狀值,或為該欄位提供判斷式;本例直接比對的是最上層屬性值。
使用 filter() 方法
如果條件固定且事先已知,可以直接在判斷式中寫出各項條件,並以邏輯 AND 運算子(&&)連接。只有每項比較都成立時,使用者才會被保留。這個完整範例使用相同的資料,篩選結果也與動態條件的版本相同。
const filter = {
address: 'India',
name: 'Aleena'
};
const users = [
{name: 'John Doe', email: 'johndoe@mail.com', age: 25, address: 'USA'},
{name: 'Aleena', email: 'aleena@mail.com', age: 35, address: 'India'},
{name: 'Mark Smith', email: 'marksmith@mail.com', age: 28, address: 'England'}
];
const filteredUsers = users.filter(
(user) => user.name === filter.name && user.address === filter.address
);
console.log(filteredUsers);
[
{
name: 'Aleena',
email: 'aleena@mail.com',
age: 35,
address: 'India'
}
]
當欄位與比較規則屬於程式本身的邏輯時,適合使用這種直接寫法;當要求比對的欄位可能改變時,則適合使用動態寫法。也可以參閱原始的 JSFiddle 範例。
請讓判斷式專注於納入結果的規則:要保留的元素回傳真值,要排除的元素回傳假值。由於 && 會採用短路求值,只有前面的比較成立時才會執行後續比較。若某項較早的比較能以較低成本排除許多元素,可以調整檢查順序,同時確保條件的意思清楚。