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






