成為出色的問題解決者(這就是開發人員)沒有捷徑可走。
精通是以練習為代價的。 由于算法和數據結構構成了每個軟件的支柱,因此練習它們應該是您的首要任務。 作為最常用的存儲值序列的數據結構,數組是必不可少的。
今天,我們將通過學習如何來磨練我們的技能:
*展平一個數組
* 刪除數組中的重復項
*從對象數組中刪除重復項
*對對象數組進行排序
*合并兩個數組
*返回兩個數組之間的差異
*檢查數組是否包含重復元素
*返回兩個數組的交集
*查找數組中最長的字符串
俗話說“熟能生巧”。 讓我們搞定它
如何展平數組:
最簡單的方法是使用內置的 .flat() 方法。flat() 方法采用可選的最大深度參數。
例如,給定以下數組:
const arr = [1, 2, [3, 4], [[5, 6], [7, 8]]];
展平的代碼是:
const flattened = arr.flat(2); //最大深度
console.log(flattened); // [1, 2, 3, 4, 5, 6, 7, 8]
flat() 方法返回一個新數組,所有子數組以遞歸方式連接到指定深度。
您還可以創建自己的遞歸函數,迭代數組的元素并將它們添加到新數組中,一次一個。
- 如果一個元素是一個數組,該函數應該以該元素作為參數調用自身,然后將結果數組連接到新數組。
- 如果一個元素不是數組,函數應該簡單地將它添加到新數組中。
這是一個示例,說明如何編寫遞歸函數來展平數組:
function flatten(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
const arr = [1, [2, [3, [4]]], 5];
console.log(flatten(arr)); // [1, 2, 3, 4, 5]
您可以使用 .reduce() 方法和三元運算符使此函數更加簡潔。
function flatten(arr) {
return arr.reduce((accumulator, currentItem) =>
Array.isArray(currentItem)
? accumulator.concat(flatten(currentItem))
: accumulator.concat(currentItem),
[]);
}
此函數具有線性時間復雜度(這意味著它對大型數組很有效)。它還具有恒定的空間復雜度(這意味著它不會隨著數組大小的增加而占用更多內存)。
如何從數組中刪除重復項:
到目前為止,刪除數組重復項的最簡單和更簡潔的方法是使用 Set 對象。
Set 對象僅存儲唯一值,因此您可以從數組創建一個新集合,然后使用 Array.from() 方法將該集合轉換回數組。
這是您可以使用 Set 對象執行此操作的一種方法:
const arr = [1, 2, 3, 1, 2, 3, 4, 5];
const unique = Array.from(new Set(arr));
console.log(unique); // [1, 2, 3, 4, 5]
您還可以使用我最喜愛的 .reduce()
const arr = [1, 2, 3, 1, 2, 3, 4, 5]
arr.reduce((accumulator, currentItem) => {
if (!accumulator.includes(currentItem))
accumulator.push(currentItem)
return accumulator
},[])
如何對對象數組進行排序
要對對象數組進行排序,您必須從對象中選擇一個屬性來對數組進行排序。
然后,您可以調用 .sort() 并將其傳遞給比較器函數。
這是比較器函數的工作原理:
- 需要兩個參數
- 如果第一個應該在第二個之前出現,則返回負值
- 如果第一個應該在第二個之后,它返回一個正值
- 如果值相等,則返回 0。
以下是如何根據 name 屬性的值對對象數組進行排序:
const arr = [
{name: 'Bob', age: 30},
{name: 'Alice', age: 25},
{name: 'Charlie', age: 35}
];
arr.sort((a, b) => {
if (a.name < b.name) { //你可以根據任意屬性排序
return -1;
} else if (a.name > b.name) {
return 1;
} else {
return 0;
}
});
/*
[
{name: 'Alice', age: 25},
{name: 'Bob', age: 30},
{name: 'Charlie', age: 35}
] */
您還可以使用三元運算符來制作單行版本:
arr.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
注意:有時嵌套的三元組可能難以閱讀。
請記住,sort() 方法會修改原始數組,因此如果您想保留原始數組,您應該先復制它。
如何合并2個數組
要合并兩個數組,您可以使用 concat() 方法。concat() 方法返回一個包含兩個數組元素的新數組。
以下是如何使用 concat() 合并兩個數組的示例:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = arr1.concat(arr2);
console.log(merged); // [1, 2, 3, 4, 5, 6]
更高級的或者更確切地說是 ES6 版本使用擴展運算符 (...)。擴展運算符將數組的元素擴展為單獨的參數。
這就是它的樣子
const merged = [...arr1, ...arr2];
console.log(merged); // [1, 2, 3, 4, 5, 6]
有兩種方法:
- 創建一個包含兩個數組元素的新數組
- 不要修改原始數組。
如果你不介意修改源數組,您可以簡單地使用 .push() 將另一個數組的元素添加到第一個數組的末尾。
arr1.push(...arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
返回 2 個數組之間的差異
有以下幾種區別:
- 非對稱的
- 對稱的
非對稱
- 在第一個數組中但不在第二個數組中的元素
對稱
- 在第一個數組中但不在第二個數組中的元素,以及在第二個數組中但不在第一個數組中的元素
以下是如何使用 filter() 方法查找兩個數組之間的非對稱差異:
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];
const difference = arr1.filter(x => !arr2.includes(x));
console.log(difference); // [1, 2]
以下是為了獲得對稱差異:
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];
const difference = arr1
.filter(x => !arr2.includes(x))
.concat(arr2.filter(x => !arr1.includes(x)));
console.log(difference); // [1, 2, 6, 7]
這種方法返回一個新數組并且不修改原始數組。
或者,您可以使用 Set 對象及其 .has() 而不是 .includes()
非對稱差異:
const set = new Set(arr2);
const difference = arr1.filter(x => !set.has(x));
console.log(difference); // [1, 2]
對稱差異:
const set = new Set(arr2);
const set1 = new Set(arr1)
const difference = arr1
.filter(x => !set.has(x))
.concat(arr2.filter(x => !set1.has(x)));
console.log(difference); // [1, 2, 6, 7]
如何檢查數組是否包含重復元素
最簡單的方法是使用 Set 對象和 size 屬性。
Set 對象僅存儲唯一值,因此您可以從數組創建一個集合并將該集合的大小與原始數組的大小進行比較。
如果集合的大小小于數組的大小,則意味著數組包含重復元素。
以下是您的操作方式:
const arr = [1, 2, 3, 4, 5, 5];
const hasDuplicates = new Set(arr).size !== arr.length;
console.log(hasDuplicates); // true
您可以使用對象(也稱為散列或字典)實現相同的目的
當您遍歷數組時,您將當前值設置為鍵,將 true 設置為鍵的值。
如果您嘗試訪問一個鍵并且那里已經有一個值,則意味著您找到了一個重復項。
這是其中一種方法:
const hasDuplicates = (arr) => {
let hash = {}
for(let i = 0; i < arr.length; i++){
if(!hash[arr[i]]){
hash[arr[i]] = true
} else {
return true;
}
}
return false
}
console.log(hasDuplicates(arr)); // true
這兩種方法都創建一個新對象(集合或哈希對象)并且不修改原始數組。它們還具有線性時間復雜度(它們對大型數組很有效)。
如何返回兩個數組之間的交集
最常見的方法是使用 filter() 和 includes()。
代碼如下:
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];
const intersection = arr1.filter(x => arr2.includes(x));
console.log(intersection); // [3, 4, 5]
這種方法返回一個新數組并且不修改原始數組。
作為替代方案,您可以(再次)使用 Set 對象和 .has() 方法
const set = new Set(arr2);
const intersection = arr1.filter(x => set.has(x));
console.log(intersection); // [3, 4, 5]
你看到模式了嗎? 每當使用普通對象解決問題時,您都可以使用 Set創建一個版本,反之亦然。
如何找到數組中最長的字符串
為此,您可以使用我們流行的 .reduce() 方法和一個函數來比較這些值。
比較器函數將當前字符串的長度與前一個最長字符串的長度進行比較,如果更長則返回當前字符串,否則返回前一個最長字符串。
你可以這樣做:
const arr = ['short', 'medium', 'long', 'longest'];
const longest = arr.reduce((acc, x) => x.length > acc.length ? x : acc, '');
console.log(longest); // 'longest'
這種方法創建一個新變量(acc 或累加器)并且不修改原始數組。
時間復雜度是線性的(意味著它對大型數組是有效的)。
同樣可以通過使用 sort() 方法和擴展運算符 (...) 來更簡潔地找到數組中最長的字符串:
const longest = [...arr].sort((a, b) => b.length - a.length)[0];
console.log(longest); // 'longest'
總結
在本文中我們介紹了:
*展平一個數組
* 刪除數組中的重復項
*從對象數組中刪除重復項
*對對象數組進行排序
*合并兩個數組
*返回兩個數組之間的差異
*檢查數組是否包含重復元素
*返回兩個數組的交集
*查找數組中最長的字符串
謝謝閱讀!