
本篇我们将继续介绍 radash 中其他 Array 相关方法,本系列文章的目的是让你在会使用 radash 的同时,了解其中的原理,通过源码解析让你知其然更知其所以然。在某些时候你甚至可以用类似思想自己写一些方法。一定不要错过充实自己开发技能包的机会!
前言
- 前篇我们已经介绍了 radash 的相关信息和部分 Array 相关方法,详情可前往主页查看;
- 本篇我们继续介绍 radash 中 Array 的其他相关方法;
Radash 的 Array 相关方法详解
first:获取数组第一项,不存在返回默认值
- 使用说明
- 参数:目标数组,或者传递两个参数空数组和默认值;
- 返回值:传目标数组则返回目标数组的第一项,传空数组和默认值则返回默认值。
- 使用代码示例
| import { first } from 'radash' |
| |
| const gods = ['lufee', 'loki', 'zeus'] |
| |
| first(gods) |
| first([], 'zuoluo') |
- 源码解析
| |
| |
| export const first = <T>( |
| array: readonly T[], |
| defaultValue: T | null | undefined = undefined |
| ) => { |
| |
| |
| return array?.length > 0 ? array[0] : defaultValue |
| } |
flat:数组扁平化 —— 把包含多个数组的数组转为一个数组(注意不会递归)
- 使用说明
- 参数:包含多个数组的数组;
- 返回值:降低一维后的数组;
- 注意:不会递归降维,只能降一维。
- 使用代码示例
| import { flat } from 'radash' |
| |
| const gods = [['shy', 'ning'], ['jkl']] |
| |
| flat(gods) |
- 源码解析
| |
| |
| export const flat = <T>(lists: readonly T[][]): T[] => { |
| |
| return lists.reduce((acc, list) => { |
| |
| acc.push(...list) |
| |
| return acc |
| }, []) |
| } |
- 方法流程说明:
- 使用
reduce
方法遍历二维数组 lists
。reduce
方法的累加器 acc
是一个一维数组,用于收集所有子数组的元素。
- 对于
lists
中的每个子数组 list
,使用展开语法 ...
将其元素添加到累加器数组 acc
中。
- 每次迭代结束后,返回更新的累加器
acc
。
- 当
reduce
方法完成遍历后,返回最终的累加器 acc
,这时它包含了 lists
中所有子数组的元素,形成了一个扁平化的一维数组。
- 提示:这个
flat
函数在功能上类似于 Array.prototype.flat 方法,但是它是手动实现的,适用于不支持内建 flat
方法的环境。
fork:按条件将数组拆分成两个数组,满足条件的一个,不满足条件的一个
- 使用说明
- 参数:目标数组,条件函数;
- 返回值:返回两个数组,一个保存满足条件的项,另一个保存不满足条件的项。
- 使用代码示例
| 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) |
- 源码解析
| |
| |
| export const fork = <T>( |
| list: readonly T[], |
| condition: (item: T) => boolean |
| ): [T[], T[]] => { |
| |
| if (!list) return [[], []] |
| |
| |
| return list.reduce( |
| (acc, item) => { |
| |
| const [a, b] = acc |
| |
| if (condition(item)) { |
| return [[...a, item], b] |
| } else { |
| return [a, [...b, item]] |
| } |
| }, |
| [[], []] as [T[], T[]] |
| ) |
| } |
- 方法流程说明:
- 首先检查传入的数组
list
是否为空。如果为空,返回一对空数组。
- 使用
reduce
方法遍历 list
数组。reduce
方法的累加器 acc
是一个包含两个子数组的元组 [T[], T[]]
。
- 对于
list
中的每个元素 item
,检查它是否满足条件函数 condition
。
- 如果条件函数返回
true
,则将该元素添加到累加器的第一个子数组 a
。如果条件函数返回 false
,则将该元素添加到第二个子数组 b
。
- 在每次迭代结束后,返回更新后的累加器
[a, b]
。
- 当
reduce
方法完成遍历后,返回最终的累加器 [a, b]
,它包含了根据条件函数分离的两个子数组。
group:根据条件函数指定的key构建一个统计对象,key 为指定的 key 有哪些 value ,value 为对应对象
- 使用说明
- 使用代码示例
| 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) |
- 源码解析
| |
| |
| export const group = <T, Key extends string | number | symbol>( |
| array: readonly T[], |
| getGroupId: (item: T) => Key |
| |
| ): Partial<Record<Key, T[]>> => { |
| |
| return array.reduce((acc, item) => { |
| |
| const groupId = getGroupId(item) |
| |
| if (!acc[groupId]) acc[groupId] = [] |
| |
| acc[groupId].push(item) |
| |
| return acc |
| }, {} as Record<Key, T[]>) |
| } |
- 方法流程说明:
- 遍历传入的数组
array
,对每个元素使用 getGroupId
函数来确定它应该属于哪个组。
- 对于每个元素,检查累加器
acc
(一个对象)中是否已经有一个数组存在于以 groupId
为键的位置。如果没有,就在那个位置创建一个空数组。
- 将当前元素
item
添加到 acc[groupId]
数组中。
- 继续处理数组的下一个元素,直到所有元素都被处理完毕。
- 返回累加器
acc
,它现在包含了按 groupId
分组的元素数组。
- tips:在TypeScript中,
Partial<Record<Key, T[]>>
是一种类型,它表示一个对象,这个对象的键可以是 Key
类型,而每个键对应的值是 T[]
类型的数组。Partial
和 Record
都是TypeScript中的高级类型。
intersects:判断两个数组是否有公共项,返回一个布尔值
- 使用说明
- 参数:数组1,数组2,可选条件函数(用于提取随机标识符,对对象数组进行操作时);
- 返回值:有返回true,否则返回false。
- 使用代码示例
| import { intersects } from 'radash' |
| |
| const oceanFish = ['tuna', 'tarpon'] |
| const lakeFish = ['bass', 'trout'] |
| |
| intersects(oceanFish, lakeFish) |
| |
| const brackishFish = ['tarpon', 'snook'] |
| |
| intersects(oceanFish, brackishFish) |
- 源码解析
| |
| |
| export const intersects = <T, K extends string | number | symbol>( |
| listA: readonly T[], |
| listB: readonly T[], |
| identity?: (t: T) => K |
| ): boolean => { |
| |
| if (!listA || !listB) return false |
| |
| const ident = identity ?? ((x: T) => x as unknown as K) |
| |
| const dictB = listB.reduce((acc, item) => { |
| acc[ident(item)] = true |
| return acc |
| }, {} as Record<string | number | symbol, boolean>) |
| |
| return listA.some(value => dictB[ident(value)]) |
| } |
- 方法流程说明:
- 检查传入的数组
listA
和 listB
是否存在。如果任何一个不存在,返回 false
。
- 如果未提供
identity
函数,则使用一个默认函数,它将每个元素 x
强制转换为 K
类型,作为其唯一标识符。
- 遍历数组
listB
,使用 reduce
方法和 ident
函数将其元素映射到一个记录对象 dictB
中,其中键是元素的唯一标识符,值为 true
。
- 使用
some
方法检查数组 listA
中是否有任何元素的唯一标识符存在于 dictB
中。如果存在,some
方法会返回 true
,表示两个数组有交集。
- 如果
listA
中没有任何元素的唯一标识符在 dictB
中找到,some
方法返回 false
,表示两个数组没有交集。
- 提示:
??
表示 TypeScript 中的空值合并运算符 。这个运算符用于提供一个默认值,当左侧的操作数 identity
是 null
或 undefined
时,就会使用右侧的操作数作为默认值。x as unknown as K
是 Typescript 的类型断言。
下期我们将介绍以下方法
- iterate:把一个函数迭代执行指定次数;
- last:输出数组的最后一项,如果数组为空则输出传入的默认值;
- list:创建包含特定项的数组;
- max:获取对象数组中指定标识符最大的项;
- merge:合并数组,并且会覆盖第一个数组;
- min:获取对象数组中指定标识符最小的项;
- objectify:根据函数映射的键与值把数组转换为字典对象;
- range:根据步长生成一个数值范围内的迭代值;
- replaceOrAppend:替换对象数组中的项或是追加项(条件函数不满足时追加);
- replace:替换数组中的第一个匹配项。
写在后面
- 后续作者会整理一份方法目录上传,方便没法访问外网的朋友查看使用。
- 该系列会在每周五更新,遇节假日提前。
- 大家有任何问题或者见解,欢迎评论区留言交流!!!
- 点击访问:radash 官网
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)