前言

  • 前篇我们已经介绍了 radash 的相关信息和部分 Array 相关方法,详情可前往主页查看;
  • 本篇我们继续介绍 radash 中 Array 的其他相关方法;

Radash 的 Array 相关方法详解

first:获取数组第一项,不存在返回默认值

  1. 使用说明

    • 参数:目标数组,或者传递两个参数空数组和默认值;
    • 返回值:传目标数组则返回目标数组的第一项,传空数组和默认值则返回默认值。
  2. 使用代码示例
  1. import { first } from 'radash'
  2. const gods = ['lufee', 'loki', 'zeus']
  3. first(gods) // => 'lufee'
  4. first([], 'zuoluo') // => 'zuoluo'
  1. 源码解析
  1. // 定义一个泛型函数 `first`,它接收一个具有只读属性的泛型数组 `array`,
  2. // 和一个可选的默认值 `defaultValue`,其类型可以是泛型 `T` 或 `null` 或 `undefined`,默认值为 `undefined`。
  3. export const first = <T>(
  4. array: readonly T[],
  5. defaultValue: T | null | undefined = undefined
  6. ) => {
  7. // 如果数组存在且长度大于0,返回数组的第一个元素。
  8. // 否则,返回提供的默认值 `defaultValue`。
  9. return array?.length > 0 ? array[0] : defaultValue
  10. }
  • 方法流程说明:

    1. 检查传入的数组 array 是否存在并且长度是否大于0。
    2. 如果数组存在且不为空(长度大于0),则返回数组的第一个元素 array[0]
    3. 如果数组不存在或为空,返回 defaultValue

    这个函数对于需要安全地访问数组第一个元素而不抛出错误的情况很有用,特别是在不确定数组是否为空的情况下。通过提供一个默认值,你可以避免在数组为空时访问未定义的索引。如果没有提供默认值,函数将默认返回 undefined

flat:数组扁平化 —— 把包含多个数组的数组转为一个数组(注意不会递归)

  1. 使用说明

    • 参数:包含多个数组的数组;
    • 返回值:降低一维后的数组;
    • 注意:不会递归降维,只能降一维
  2. 使用代码示例
  1. import { flat } from 'radash'
  2. const gods = [['shy', 'ning'], ['jkl']]
  3. flat(gods) // => [shy, ning, jkl]
  1. 源码解析
  1. // 定义一个泛型函数 `flat`,它接收一个具有只读属性的二维泛型数组 `lists`,
  2. // 并返回一个扁平化的一维数组。
  3. export const flat = <T>(lists: readonly T[][]): T[] => {
  4. // 使用数组的 `reduce` 方法来累积(合并)所有子数组的元素。
  5. return lists.reduce((acc, list) => {
  6. // 使用 `push` 方法的展开语法(...)将当前处理的子数组 `list` 的所有元素添加到累加器 `acc` 中。
  7. acc.push(...list)
  8. // 返回更新后的累加器 `acc`,以便它可以在下一次迭代中使用。
  9. return acc
  10. }, []) // 初始化累加器 `acc` 为一个空数组。
  11. }
  • 方法流程说明:

    1. 使用 reduce 方法遍历二维数组 listsreduce 方法的累加器 acc 是一个一维数组,用于收集所有子数组的元素。
    2. 对于 lists 中的每个子数组 list,使用展开语法 ... 将其元素添加到累加器数组 acc 中。
    3. 每次迭代结束后,返回更新的累加器 acc
    4. reduce 方法完成遍历后,返回最终的累加器 acc,这时它包含了 lists 中所有子数组的元素,形成了一个扁平化的一维数组。
    5. 提示:这个 flat 函数在功能上类似于 Array.prototype.flat 方法,但是它是手动实现的,适用于不支持内建 flat 方法的环境。

fork:按条件将数组拆分成两个数组,满足条件的一个,不满足条件的一个

  1. 使用说明

    • 参数:目标数组,条件函数;
    • 返回值:返回两个数组,一个保存满足条件的项,另一个保存不满足条件的项。
  2. 使用代码示例
  1. import { fork } from 'radash'
  2. const gods = [
  3. {
  4. name: 'Uzi',
  5. power: 100
  6. },
  7. {
  8. name: 'Xiaohu',
  9. power: 98
  10. },
  11. {
  12. name: 'Ming',
  13. power: 72
  14. },
  15. {
  16. name: 'Mlxg',
  17. power: 100
  18. }
  19. ]
  20. const [finalGods, lesserGods] = fork(gods, f => f.power > 90) // [[Uzi, Xiaohu, Mlxg], [Ming]]
  1. 源码解析
  1. // 定义一个泛型函数 `fork`,它接受一个具有只读属性的泛型数组 `list`,
  2. // 和一个条件函数 `condition`,根据此函数将 `list` 中的元素分成两组。
  3. export const fork = <T>(
  4. list: readonly T[],
  5. condition: (item: T) => boolean
  6. ): [T[], T[]] => {
  7. // 如果传入的 `list` 为空,则返回两个空数组。
  8. if (!list) return [[], []]
  9. // 使用数组的 `reduce` 方法来累积分离出的两个子数组。
  10. return list.reduce(
  11. (acc, item) => {
  12. // 从累加器中解构出两个子数组 a 和 b。
  13. const [a, b] = acc
  14. // 如果当前元素 `item` 满足条件函数 `condition`,将其添加到数组 a,否则添加到数组 b。
  15. if (condition(item)) {
  16. return [[...a, item], b]
  17. } else {
  18. return [a, [...b, item]]
  19. }
  20. },
  21. [[], []] as [T[], T[]] // 初始化累加器为两个空数组。
  22. )
  23. }
  • 方法流程说明:

    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. 使用代码示例
  1. import { group } from 'radash'
  2. const fish = [
  3. {
  4. name: 'Marlin',
  5. source: 'ocean'
  6. },
  7. {
  8. name: 'Bass',
  9. source: 'lake'
  10. },
  11. {
  12. name: 'Trout',
  13. source: 'lake'
  14. }
  15. ]
  16. const fishBySource = group(fish, f => f.source) // => { ocean: [marlin], lake: [bass, trout] }
  1. 源码解析
  1. // 定义一个泛型函数 `group`,它接受一个具有只读属性的泛型数组 `array`,
  2. // 和一个函数 `getGroupId`,该函数用于从数组元素中提取一个标识符作为组的键。
  3. export const group = <T, Key extends string | number | symbol>(
  4. array: readonly T[],
  5. getGroupId: (item: T) => Key
  6. // 返回一个对象,其键是通过 `getGroupId` 函数提取的标识符,键对应的值是具有相同标识符的元素数组。
  7. ): Partial<Record<Key, T[]>> => {
  8. // 使用数组的 `reduce` 方法来累积分组结果。
  9. return array.reduce((acc, item) => {
  10. // 使用 `getGroupId` 函数从当前元素 `item` 中获取组标识符 `groupId`。
  11. const groupId = getGroupId(item)
  12. // 如果累加器 `acc` 中还没有这个组标识符的键,初始化为一个空数组。
  13. if (!acc[groupId]) acc[groupId] = []
  14. // 将当前元素 `item` 添加到对应组标识符的数组中。
  15. acc[groupId].push(item)
  16. // 返回更新后的累加器 `acc`,以便它可以在下一次迭代中使用。
  17. return acc
  18. }, {} as Record<Key, T[]>) // 初始化累加器为一个空对象。
  19. }
  • 方法流程说明:

    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. 使用代码示例
  1. import { intersects } from 'radash'
  2. const oceanFish = ['tuna', 'tarpon']
  3. const lakeFish = ['bass', 'trout']
  4. intersects(oceanFish, lakeFish) // => false
  5. const brackishFish = ['tarpon', 'snook']
  6. intersects(oceanFish, brackishFish) // => true
  1. 源码解析
  1. // 定义一个泛型函数 `intersects`,它接受两个具有只读属性的泛型数组 `listA` 和 `listB`,
  2. // 以及一个可选的函数 `identity`,用于从数组元素中提取一个唯一标识符。
  3. export const intersects = <T, K extends string | number | symbol>(
  4. listA: readonly T[],
  5. listB: readonly T[],
  6. identity?: (t: T) => K
  7. ): boolean => {
  8. // 如果 `listA` 或 `listB` 不存在,返回 false。
  9. if (!listA || !listB) return false
  10. // 如果 `identity` 函数未提供,则使用默认函数,它将元素作为其自己的标识符。
  11. const ident = identity ?? ((x: T) => x as unknown as K)
  12. // 使用 `listB` 的元素创建一个记录对象 `dictB`,键是通过 `ident` 函数提取的唯一标识符,值为 `true`。
  13. const dictB = listB.reduce((acc, item) => {
  14. acc[ident(item)] = true
  15. return acc
  16. }, {} as Record<string | number | symbol, boolean>)
  17. // 检查 `listA` 中是否有元素的唯一标识符存在于 `dictB` 中。
  18. return listA.some(value => dictB[ident(value)])
  19. }
  • 方法流程说明:

    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 官网

lodash已死?radash最全使用介绍(附源码说明)—— Array方法篇(2)的更多相关文章

  1. php 品牌全车零件订购平台( 带采集数据 及 账号自动登陆【已绕过https证书加密】,php源码 ,QQ: 876635409 )

    php捷豹路虎 品牌全车零件订购平台  ( 带采集数据 及 账号自动登陆[已绕过https证书加密],php源码 ,QQ: 876635409 [由于咨询用户太多,请备注:汽车配件]) 一.php+m ...

  2. IPerf——网络测试工具介绍与源码解析(4)

    上篇随笔讲到了TCP模式下的客户端,接下来会讲一下TCP模式普通场景下的服务端,说普通场景则是暂时不考虑双向测试的可能,毕竟了解一项东西还是先从简单的情况下入手会快些. 对于服务端,并不是我们认为的直 ...

  3. 日志组件Log2Net的介绍和使用(附源码开源地址)

    Log2Net是一个用于收集日志到数据库或文件的组件,支持.NET和.NetCore平台. 此组件自动收集系统的运行日志(服务器运行情况.在线人数等).异常日志.程序员还可以添加自定义日志. 该组件支 ...

  4. 死磕 java同步系列之Phaser源码解析

    问题 (1)Phaser是什么? (2)Phaser具有哪些特性? (3)Phaser相对于CyclicBarrier和CountDownLatch的优势? 简介 Phaser,翻译为阶段,它适用于这 ...

  5. 死磕 java同步系列之StampedLock源码解析

    问题 (1)StampedLock是什么? (2)StampedLock具有什么特性? (3)StampedLock是否支持可重入? (4)StampedLock与ReentrantReadWrite ...

  6. 死磕 java同步系列之ReentrantLock源码解析(二)——条件锁

    问题 (1)条件锁是什么? (2)条件锁适用于什么场景? (3)条件锁的await()是在其它线程signal()的时候唤醒的吗? 简介 条件锁,是指在获取锁之后发现当前业务场景自己无法处理,而需要等 ...

  7. 死磕 java同步系列之ReentrantLock源码解析(一)——公平锁、非公平锁

    问题 (1)重入锁是什么? (2)ReentrantLock如何实现重入锁? (3)ReentrantLock为什么默认是非公平模式? (4)ReentrantLock除了可重入还有哪些特性? 简介 ...

  8. Android IntentService使用介绍以及源码解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...

  9. 死磕 java同步系列之CyclicBarrier源码解析——有图有真相

    问题 (1)CyclicBarrier是什么? (2)CyclicBarrier具有什么特性? (3)CyclicBarrier与CountDownLatch的对比? 简介 CyclicBarrier ...

  10. 死磕 java同步系列之Semaphore源码解析

    问题 (1)Semaphore是什么? (2)Semaphore具有哪些特性? (3)Semaphore通常使用在什么场景中? (4)Semaphore的许可次数是否可以动态增减? (5)Semaph ...

随机推荐

  1. sklearn学习笔记之线性回归

    AI时代扑面而来,在大众面对ChatGPT和Sora发出无数惊叹号的时候,我决定不再只当一个AI时代的API调用者,而是去学习机器学习技术本身. 刚好公司也要往人工智能方向发展的计划,于是我开始从基础 ...

  2. 从零开始写 Docker(二)---优化:使用匿名管道传递参数

    本文为从零开始写 Docker 系列第二篇,主要在 mydocker run 命令基础上优化参数传递方式,改为使用 runC 同款的匿名管道传递参数. 如果你对云原生技术充满好奇,想要深入了解更多相关 ...

  3. sqlserver数据库jar包下载

    链接:https://pan.baidu.com/s/1mCx5JpVpmU6uUaqMITxP_Q提取码:4piq 说明:若链接失效,联系会及时补上!

  4. 如何设计一个高性能的图 Schema

    本文整理自青藤云安全工程师--文洲在青藤云技术团队内部分享,分享视频参考:https://www.bilibili.com/video/BV1r64y1R72i 图数据库的性能和 schema 的设计 ...

  5. STL-priority_queue模拟实现

    #include<deque> //测试用 #include<vector>//测试用 #include"9Date.h"//测试用 #include< ...

  6. TCP和UDP可以使用同一个端口号吗?

    TCP和UDP可以使用同一个端口号吗? 首先说答案:可以.怎么理解呢? 我想这个问题要从计算机网络通信谈起,学过计算机网络的同学,可能都还记得7层或者4层网络模型,TCP/UDP属于其中的传输层协议, ...

  7. Postman/Jmeter工具实现接口测试,为什么还要用代码来实现接口自动化测试?

    这种工具包括一些开源框架最大缺点就是不够灵活,如果是单接口的测试还行,但是有的项目接口比较庞大和负责,这种情况下就不大适用工具(工具适用于小型项目,代码适用于中大型项目) 主要有以下几个原因: 1敏捷 ...

  8. Java 常用类 于 StringBuffer 和 StringBuilder的使用 + String三者的异同

    1 package com.bytezero.stringclass; 2 3 import org.junit.Test; 4 5 /** 6 * 关于 StringBuffer 和 StringB ...

  9. centos7挂载硬盘(大于2T)

    配置方法: 1.root账户下,执行 fdisk -l 命令查看挂载的硬盘设备,假设设备号为/dev/sdb,接下来我们使用parted命令来进行GPT分区 2.使用parted命令进行GPT分区 # ...

  10. Landsat 7的热红外波段有2个该如何选择?

      本文介绍Landsat 7遥感影像数据中B61.B62两个热红外波段的区别,以及研究应用时二者选择的依据.   Landsat 7遥感影像数据具有2个热红外波段,分别是Band 61与Band 6 ...