題開始,數組去重,即從一個數組中移除所有重復的元素,確保每個元素只出現一次,是這一類問題的核心。
1. filter() 方法配合 indexOf()
const uniqueArray=array.filter((item, index, self)=> {
return self.indexOf(item)===index;
});
該方法利用 filter() 遍歷數組,對于每個元素,通過 indexOf() 查找其在原數組中的第一個索引。如果當前元素的索引與正在遍歷的索引相同,說明這是該元素在數組中的首次出現,保留該元素;否則,忽略該元素。
2. reduce() 方法
const uniqueArray=array.reduce((acc, current)=> {
return acc.includes(current) ? acc : [...acc, current];
}, []);
這里使用 reduce() 函數將數組累積到一個新的數組(acc)中。在每次迭代中,檢查當前元素是否已存在于累積數組中。若不存在,則將其添加至累積數組;否則,跳過該元素。
1. 使用擴展運算符與解構賦值
const uniqueArray=[...new Set(array)];
這種方法簡潔高效,利用 ES6 的 Set 數據結構自動去除重復元素的特性,再通過擴展運算符將 Set 轉換回數組。Set 是一種特殊的集合,不允許重復元素存在,因此插入過程會自動過濾重復項。
2. 利用 Map 數據結構
const uniqueArray=Array.from(new Map(array.map(item=> [item, item])).values());
盡管不如直接使用 Set 直觀,但此方法同樣有效。它首先將數組映射為鍵值對相同的 Map,由于 Map 鍵的唯一性,重復的數組元素會被自動忽略。然后通過 Array.from() 和 Map.values() 將 Map 的值(即無重復元素)轉換回數組。
1. 雙重循環
const uniqueArray=[];
for (let i=0; i < array.length; i++) {
let isDuplicate=false;
for (let j=0; j < i; j++) {
if (array[i]===array[j]) {
isDuplicate=true;
break;
}
}
if (!isDuplicate) {
uniqueArray.push(array[i]);
}
}
這種方法最直觀也最基礎,通過外層循環遍歷數組,內層循環檢查當前元素是否與之前的所有元素重復。如果沒有重復,則將其添加到結果數組中。雖然理解簡單,但時間復雜度較高,不適用于大型數據集。
2. 利用對象作為哈希表
const uniqueArray=[];
const hashTable={};
for (let i=0; i < array.length; i++) {
const item=array[i];
if (!hashTable[item]) {
uniqueArray.push(item);
hashTable[item]=true;
}
}
這種方法利用對象作為哈希表,以數組元素作為鍵。在遍歷過程中,若元素尚未作為對象的鍵存在,則添加到結果數組并將其設置為哈希表的鍵。由于對象屬性查找的時間復雜度接近 O(1),這種方法在處理大量數據時比雙重循環更為高效。
1. 性能比較
2. 優化策略
let arr=["頭條", "頭條", "頭條", "plzbefat", "plzbefat", "plzbefat"];
let arrUnique=arr.filter((v, i, self)=> self.indexOf(v)===i); //過濾掉已經存在的值
console.log(arrUnique);
let arr=["頭條", "頭條", "頭條", "plzbefat", "plzbefat", "plzbefat"];
let arrUnique=[...new Set(arr)];//值的集合 不能重復
console.log(arrUnique);
關于set函數:
Set 對象允許你存儲任何類型的唯一值,無論是原始值或者是對象引用。
已知如下數組: var arr=[ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; 編寫一個程序將數組扁平化去并除其中重復部分數據,最終得到一個升序且不重復的數組
組實例的 flat(),flatMap()
數組的成員有時還是數組,Array.prototype.flat()用于將嵌套的數組“拉平”,變成一維的數組。該方法返回一個新數組,對原數據沒有影響。
上面代碼中,原數組的成員里面有一個數組,flat()方法將子數組的成員取出來,添加在原來的位置。
flat()默認只會“拉平”一層,如果想要“拉平”多層的嵌套數組,可以將flat()方法的參數寫成一個整數,表示想要拉平的層數,默認為1。
上面代碼中,flat()的參數為2,表示要“拉平”兩層的嵌套數組。
如果不管有多少層嵌套,都要轉成一維數組,可以用Infinity關鍵字作為參數。
如果原數組有空位,flat()方法會跳過空位
flatMap()方法對原數組的每個成員執行一個函數(相當于執行Array.prototype.map()),然后對返回值組成的數組執行flat()方法。該方法返回一個新數組,不改變原數組。
flatMap()方法的參數是一個遍歷函數,該函數可以接受三個參數,分別是當前數組成員、當前數組成員的位置(從零開始)、原數組。
然后,我們來看看文章開始的那道題目如何優雅的求解
如果你還有好的方法,歡迎在下面留言,我會補充上去,供大家學習參考
參考文章:
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/8
*請認真填寫需求信息,我們會在24小時內與您取得聯系。