本教程將詳細介紹如何利用 JavaScript 中數組的 indexOf() 和 lastIndexOf() 方法,結合 Filter() 函數,高效地從一個數組中篩選出所有只出現一次的唯一元素。文章通過代碼示例和逐步解析,幫助讀者深入理解該方法的原理和應用,實現精確的去重操作。
數組唯一元素提取的需求
在日常的 javascript 開發中,我們經常會遇到需要處理數組中重復數據的情況。有時,我們不僅需要移除所有重復項以獲得一個不包含任何重復值的數組(即去重),更具體的需求是,我們希望從數組中找出那些只出現過一次的元素,而將所有出現多次的元素全部剔除。例如,給定數組 [100, 123, 100, 122, 119, 203, 123, 76, 89],我們期望的輸出是 [122, 119, 203, 76, 89]。
核心原理:indexOf() 與 lastIndexOf() 的結合應用
解決上述問題的關鍵在于巧妙地利用 JavaScript 數組的兩個原生方法:Array.prototype.indexOf() 和 Array.prototype.lastIndexOf()。
- indexOf(searchElement[, fromIndex]): 該方法返回在數組中可以找到一個給定元素的第一個(最小)索引,如果不存在,則返回 -1。它從數組的開頭(索引0)開始向后查找。
- lastIndexOf(searchElement[, fromIndex]): 該方法返回在數組中可以找到一個給定元素的最后一個(最大)索引,如果不存在,則返回 -1。它從數組的末尾開始向前查找。
當一個元素在數組中只出現一次時,它的 indexOf() 和 lastIndexOf() 返回的索引值將是相同的。因為無論是從左側查找還是從右側查找,它都只會找到同一個位置的該元素。反之,如果一個元素在數組中出現多次,那么它的 indexOf()(第一次出現的索引)將與 lastIndexOf()(最后一次出現的索引)不同。
利用這一特性,我們可以結合 Array.prototype.filter() 方法來遍歷數組,并根據每個元素 indexOf(val) === lastIndexOf(val) 的條件進行篩選。
代碼實現
以下是使用 filter()、indexOf() 和 lastIndexOf() 方法實現該功能的 JavaScript 代碼示例:
立即學習“Java免費學習筆記(深入)”;
const arr = [100, 123, 100, 122, 119, 203, 123, 76, 89]; /** * 從數組中篩選出只出現一次的唯一元素 * @param {Array} data - 輸入數組 * @returns {Array} - 包含唯一元素的數組 */ const getUniqueElements = (data) => { return data.filter((val) => data.indexOf(val) === data.lastIndexOf(val)); }; const result = getUniqueElements(arr); console.log(result); // 輸出: [122, 119, 203, 76, 89]
逐步解析示例
為了更深入地理解上述代碼的工作原理,我們以一個更簡單的數組 [1, 2, 3, 1, 2] 為例,逐步分析 filter() 方法在每個元素上的判斷過程。
假設我們有數組 arr = [1, 2, 3, 1, 2]。
-
處理第一個元素 1 (索引 0):
- arr.indexOf(1) 返回 0 (從左側找到的第一個 1 的索引)。
- arr.lastIndexOf(1) 返回 3 (從右側找到的最后一個 1 的索引)。
- 0 === 3 為 false。因此,1 被過濾掉。
-
處理第二個元素 2 (索引 1):
- arr.indexOf(2) 返回 1 (從左側找到的第一個 2 的索引)。
- arr.lastIndexOf(2) 返回 4 (從右側找到的最后一個 2 的索引)。
- 1 === 4 為 false。因此,2 被過濾掉。
-
處理第三個元素 3 (索引 2):
- arr.indexOf(3) 返回 2 (從左側找到的第一個 3 的索引)。
- arr.lastIndexOf(3) 返回 2 (從右側找到的最后一個 3 的索引)。
- 2 === 2 為 true。因此,3 被保留。
-
處理第四個元素 1 (索引 3):
- arr.indexOf(1) 返回 0 (從左側找到的第一個 1 的索引)。
- arr.lastIndexOf(1) 返回 3 (從右側找到的最后一個 1 的索引)。
- 0 === 3 為 false。因此,1 被過濾掉。
-
處理第五個元素 2 (索引 4):
- arr.indexOf(2) 返回 1 (從左側找到的第一個 2 的索引)。
- arr.lastIndexOf(2) 返回 4 (從右側找到的最后一個 2 的索引)。
- 1 === 4 為 false。因此,2 被過濾掉。
經過所有元素的迭代,最終 filter() 方法將返回一個只包含 [3] 的新數組。這完美地符合了我們的預期,即只保留那些在原數組中只出現過一次的元素。
注意事項與總結
- 性能考量: 盡管這種方法簡潔易懂,但在處理非常大的數組時,其性能可能不是最優的。因為對于數組中的每個元素,indexOf() 和 lastIndexOf() 都可能需要遍歷整個數組,導致時間復雜度接近 O(n^2)。對于百萬級別以上的數據量,可以考慮使用哈希表(map 或 Object)來統計元素出現次數,從而達到 O(n) 的時間復雜度。
- 適用類型: 此方法適用于數組中包含基本數據類型(如數字、字符串、布爾值)的場景。對于包含對象或數組等引用類型的數組,indexOf() 和 lastIndexOf() 會進行嚴格相等(===)比較,這意味著它們只會查找引用地址完全相同的對象,而不會比較對象的內容。
- 可讀性: 這種解決方案的可讀性非常好,通過 indexOf 和 lastIndexOf 的語義,能夠直觀地理解其篩選唯一元素的邏輯。
通過本文的講解,您應該已經掌握了如何利用 JavaScript 的 indexOf() 和 lastIndexOf() 方法結合 filter() 函數,高效且準確地從數組中提取出所有只出現一次的唯一元素。在實際開發中,根據具體的數據規模和性能要求,您可以選擇最適合的方案。