lodash已死?radash最全使用介紹(附原始碼說明)—— Array方法篇(2)

雾散声声慢發表於2024-04-03

前言

  • 前篇我們已經介紹了 radash 的相關資訊和部分 Array 相關方法,詳情可前往主頁檢視;
  • 本篇我們繼續介紹 radash 中 Array 的其他相關方法;

Radash 的 Array 相關方法詳解

first:獲取陣列第一項,不存在返回預設值

  1. 使用說明
    • 引數:目標陣列,或者傳遞兩個引數空陣列和預設值;
    • 返回值:傳目標陣列則返回目標陣列的第一項,傳空陣列和預設值則返回預設值。
  2. 使用程式碼示例
import { first } from 'radash'

const gods = ['lufee', 'loki', 'zeus']

first(gods) // => 'lufee'
first([], 'zuoluo') // => 'zuoluo'
  1. 原始碼解析
// 定義一個泛型函式 `first`,它接收一個具有隻讀屬性的泛型陣列 `array`,
// 和一個可選的預設值 `defaultValue`,其型別可以是泛型 `T` 或 `null` 或 `undefined`,預設值為 `undefined`。
export const first = <T>(
  array: readonly T[],
  defaultValue: T | null | undefined = undefined
) => {
  // 如果陣列存在且長度大於0,返回陣列的第一個元素。
  // 否則,返回提供的預設值 `defaultValue`。
  return array?.length > 0 ? array[0] : defaultValue
}
  • 方法流程說明:

    1. 檢查傳入的陣列 array 是否存在並且長度是否大於0。
    2. 如果陣列存在且不為空(長度大於0),則返回陣列的第一個元素 array[0]
    3. 如果陣列不存在或為空,返回 defaultValue

    這個函式對於需要安全地訪問陣列第一個元素而不丟擲錯誤的情況很有用,特別是在不確定陣列是否為空的情況下。透過提供一個預設值,你可以避免在陣列為空時訪問未定義的索引。如果沒有提供預設值,函式將預設返回 undefined

flat:陣列扁平化 —— 把包含多個陣列的陣列轉為一個陣列(注意不會遞迴)

  1. 使用說明
    • 引數:包含多個陣列的陣列;
    • 返回值:降低一維後的陣列;
    • 注意:不會遞迴降維,只能降一維
  2. 使用程式碼示例
import { flat } from 'radash'

const gods = [['shy', 'ning'], ['jkl']]

flat(gods) // => [shy, ning, jkl]
  1. 原始碼解析
// 定義一個泛型函式 `flat`,它接收一個具有隻讀屬性的二維泛型陣列 `lists`,
// 並返回一個扁平化的一維陣列。
export const flat = <T>(lists: readonly T[][]): T[] => {
  // 使用陣列的 `reduce` 方法來累積(合併)所有子陣列的元素。
  return lists.reduce((acc, list) => {
    // 使用 `push` 方法的展開語法(...)將當前處理的子陣列 `list` 的所有元素新增到累加器 `acc` 中。
    acc.push(...list)
    // 返回更新後的累加器 `acc`,以便它可以在下一次迭代中使用。
    return acc
  }, []) // 初始化累加器 `acc` 為一個空陣列。
}
  • 方法流程說明:
    1. 使用 reduce 方法遍歷二維陣列 listsreduce 方法的累加器 acc 是一個一維陣列,用於收集所有子陣列的元素。
    2. 對於 lists 中的每個子陣列 list,使用展開語法 ... 將其元素新增到累加器陣列 acc 中。
    3. 每次迭代結束後,返回更新的累加器 acc
    4. reduce 方法完成遍歷後,返回最終的累加器 acc,這時它包含了 lists 中所有子陣列的元素,形成了一個扁平化的一維陣列。
    5. 提示:這個 flat 函式在功能上類似於 Array.prototype.flat 方法,但是它是手動實現的,適用於不支援內建 flat 方法的環境。

fork:按條件將陣列拆分成兩個陣列,滿足條件的一個,不滿足條件的一個

  1. 使用說明
    • 引數:目標陣列,條件函式;
    • 返回值:返回兩個陣列,一個儲存滿足條件的項,另一個儲存不滿足條件的項。
  2. 使用程式碼示例
import { fork } from 'radash'

const gods = [
  {
    name: 'Uzi',
    power: 100
  },
  {
    name: 'Xiaohu',
    power: 98
  },
  {
    name: 'Ming',
    power: 72
  },
  {
    name: 'Mlxg',
    power: 100
  }
]

const [finalGods, lesserGods] = fork(gods, f => f.power > 90) // [[Uzi, Xiaohu, Mlxg], [Ming]]
  1. 原始碼解析
// 定義一個泛型函式 `fork`,它接受一個具有隻讀屬性的泛型陣列 `list`,
// 和一個條件函式 `condition`,根據此函式將 `list` 中的元素分成兩組。
export const fork = <T>(
  list: readonly T[],
  condition: (item: T) => boolean
): [T[], T[]] => {
  // 如果傳入的 `list` 為空,則返回兩個空陣列。
  if (!list) return [[], []]
  
  // 使用陣列的 `reduce` 方法來累積分離出的兩個子陣列。
  return list.reduce(
    (acc, item) => {
      // 從累加器中解構出兩個子陣列 a 和 b。
      const [a, b] = acc
      // 如果當前元素 `item` 滿足條件函式 `condition`,將其新增到陣列 a,否則新增到陣列 b。
      if (condition(item)) {
        return [[...a, item], b]
      } else {
        return [a, [...b, item]]
      }
    },
    [[], []] as [T[], T[]] // 初始化累加器為兩個空陣列。
  )
}
  • 方法流程說明:
    1. 首先檢查傳入的陣列 list 是否為空。如果為空,返回一對空陣列。
    2. 使用 reduce 方法遍歷 list 陣列。reduce 方法的累加器 acc 是一個包含兩個子陣列的元組 [T[], T[]]
    3. 對於 list 中的每個元素 item,檢查它是否滿足條件函式 condition
    4. 如果條件函式返回 true,則將該元素新增到累加器的第一個子陣列 a。如果條件函式返回 false,則將該元素新增到第二個子陣列 b
    5. 在每次迭代結束後,返回更新後的累加器 [a, b]
    6. reduce 方法完成遍歷後,返回最終的累加器 [a, b],它包含了根據條件函式分離的兩個子陣列。

group:根據條件函式指定的key構建一個統計物件,key 為指定的 key 有哪些 value ,value 為對應物件

  1. 使用說明
    • 引數:物件陣列、條件函式;
    • 返回值:統計物件
  2. 使用程式碼示例
import { group } from 'radash'

const fish = [
  {
    name: 'Marlin',
    source: 'ocean'
  },
  {
    name: 'Bass',
    source: 'lake'
  },
  {
    name: 'Trout',
    source: 'lake'
  }
]

const fishBySource = group(fish, f => f.source) // => { ocean: [marlin], lake: [bass, trout] }
  1. 原始碼解析
// 定義一個泛型函式 `group`,它接受一個具有隻讀屬性的泛型陣列 `array`,
// 和一個函式 `getGroupId`,該函式用於從陣列元素中提取一個識別符號作為組的鍵。
export const group = <T, Key extends string | number | symbol>(
  array: readonly T[],
  getGroupId: (item: T) => Key
// 返回一個物件,其鍵是透過 `getGroupId` 函式提取的識別符號,鍵對應的值是具有相同識別符號的元素陣列。
): Partial<Record<Key, T[]>> => {
  // 使用陣列的 `reduce` 方法來累積分組結果。
  return array.reduce((acc, item) => {
    // 使用 `getGroupId` 函式從當前元素 `item` 中獲取組識別符號 `groupId`。
    const groupId = getGroupId(item)
    // 如果累加器 `acc` 中還沒有這個組識別符號的鍵,初始化為一個空陣列。
    if (!acc[groupId]) acc[groupId] = []
    // 將當前元素 `item` 新增到對應組識別符號的陣列中。
    acc[groupId].push(item)
    // 返回更新後的累加器 `acc`,以便它可以在下一次迭代中使用。
    return acc
  }, {} as Record<Key, T[]>) // 初始化累加器為一個空物件。
}
  • 方法流程說明:
    1. 遍歷傳入的陣列 array,對每個元素使用 getGroupId 函式來確定它應該屬於哪個組。
    2. 對於每個元素,檢查累加器 acc(一個物件)中是否已經有一個陣列存在於以 groupId 為鍵的位置。如果沒有,就在那個位置建立一個空陣列。
    3. 將當前元素 item 新增到 acc[groupId] 陣列中。
    4. 繼續處理陣列的下一個元素,直到所有元素都被處理完畢。
    5. 返回累加器 acc,它現在包含了按 groupId 分組的元素陣列。
    6. tips:在TypeScript中,Partial<Record<Key, T[]>> 是一種型別,它表示一個物件,這個物件的鍵可以是 Key 型別,而每個鍵對應的值是 T[] 型別的陣列。PartialRecord 都是TypeScript中的高階型別。

intersects:判斷兩個陣列是否有公共項,返回一個布林值

  1. 使用說明
    • 引數:陣列1,陣列2,可選條件函式(用於提取隨機識別符號,對物件陣列進行操作時);
    • 返回值:有返回true,否則返回false。
  2. 使用程式碼示例
import { intersects } from 'radash'

const oceanFish = ['tuna', 'tarpon']
const lakeFish = ['bass', 'trout']

intersects(oceanFish, lakeFish) // => false

const brackishFish = ['tarpon', 'snook']

intersects(oceanFish, brackishFish) // => true
  1. 原始碼解析
// 定義一個泛型函式 `intersects`,它接受兩個具有隻讀屬性的泛型陣列 `listA` 和 `listB`,
// 以及一個可選的函式 `identity`,用於從陣列元素中提取一個唯一識別符號。
export const intersects = <T, K extends string | number | symbol>(
  listA: readonly T[],
  listB: readonly T[],
  identity?: (t: T) => K
): boolean => {
  // 如果 `listA` 或 `listB` 不存在,返回 false。
  if (!listA || !listB) return false
  // 如果 `identity` 函式未提供,則使用預設函式,它將元素作為其自己的識別符號。
  const ident = identity ?? ((x: T) => x as unknown as K)
  // 使用 `listB` 的元素建立一個記錄物件 `dictB`,鍵是透過 `ident` 函式提取的唯一識別符號,值為 `true`。
  const dictB = listB.reduce((acc, item) => {
    acc[ident(item)] = true
    return acc
  }, {} as Record<string | number | symbol, boolean>)
  // 檢查 `listA` 中是否有元素的唯一識別符號存在於 `dictB` 中。
  return listA.some(value => dictB[ident(value)])
}
  • 方法流程說明:
    1. 檢查傳入的陣列 listAlistB 是否存在。如果任何一個不存在,返回 false
    2. 如果未提供 identity 函式,則使用一個預設函式,它將每個元素 x 強制轉換為 K 型別,作為其唯一識別符號。
    3. 遍歷陣列 listB,使用 reduce 方法和 ident 函式將其元素對映到一個記錄物件 dictB 中,其中鍵是元素的唯一識別符號,值為 true
    4. 使用 some 方法檢查陣列 listA 中是否有任何元素的唯一識別符號存在於 dictB 中。如果存在,some 方法會返回 true,表示兩個陣列有交集。
    5. 如果 listA 中沒有任何元素的唯一識別符號在 dictB 中找到,some 方法返回 false,表示兩個陣列沒有交集。
    6. 提示:??表示 TypeScript 中的空值合併運算子 。這個運算子用於提供一個預設值,當左側的運算元 identitynullundefined 時,就會使用右側的運算元作為預設值。x as unknown as K是 Typescript 的型別斷言。

下期我們將介紹以下方法

  • iterate:把一個函式迭代執行指定次數;
  • last:輸出陣列的最後一項,如果陣列為空則輸出傳入的預設值;
  • list:建立包含特定項的陣列;
  • max:獲取物件陣列中指定識別符號最大的項;
  • merge:合併陣列,並且會覆蓋第一個陣列;
  • min:獲取物件陣列中指定識別符號最小的項;
  • objectify:根據函式對映的鍵與值把陣列轉換為字典物件;
  • range:根據步長生成一個數值範圍內的迭代值;
  • replaceOrAppend:替換物件陣列中的項或是追加項(條件函式不滿足時追加);
  • replace:替換陣列中的第一個匹配項。

寫在後面

  • 後續作者會整理一份方法目錄上傳,方便沒法訪問外網的朋友檢視使用。
  • 該系列會在每週五更新,遇節假日提前。
  • 大家有任何問題或者見解,歡迎評論區留言交流!!!
  • 點選訪問:radash 官網

相關文章