以前我没得选,现在只想用 Array.reduce(上)

简介: 第一眼看 Array.reduce 这个函数总感觉怪怪的,用法也得花几分种才弄懂,懂了之后也不知道应用场景是啥。最近写项目的时候才慢慢对这个函数有更多的理解,可以算是 Array 类型下最强大的函数之一了。

代码仓库:github.com/Haixiang612…


前言


第一眼看 Array.reduce 这个函数总感觉怪怪的,用法也得花几分种才弄懂,懂了之后也不知道应用场景是啥。最近写项目的时候才慢慢对这个函数有更多的理解,可以算是 Array 类型下最强大的函数之一了。


API 用法


API 的用法分有无初始值两种情况:


没有初始值

const array = [1, 2, 3]
array.reduce((prev, curt) => {
  return prev + curt
}) // 1 + 2 + 3 = 6
复制代码


有初始值

const array = [1, 2, 3]
array.reduce((prev, curt) => {
  return prev + curt
}, 99) // 99 + 1 + 2 + 3 = 105
复制代码


reduce 这个函数的主要功能是将多个东西合成一个东西。大家都做过小学奥数吧,就类似于这样


image.png

reduce 所提供的功能就是这个加号,至于这怎么个加法,是由你来决定的。加法的过程可以形象地理解成贪吃蛇一样

image.png


🐍 (prev) + 💩(curt) + 💩 (curt) + 💩(curt) = 🛫 (return value)
复制代码


已有的蛇身就是 prev 参数,要吃掉的豆子就是 curt,吃完豆子的状态就是回调函数的返回值,整个 reduce 函数返回值就是这条🐍死了之后的状态。


应用场景


reduce 这个函数最难的点是想不出有什么使用场景。下面就做个抛砖引玉:

那我们先来思考一个问题:上面的例子只展示了数字的加法嘛,而 JS 里有 7 种基本数据类型:number, string, object, symbol, null, boolean, undefined。如果这些类型相加会怎么样呢?


除了这些基本类型,object 里也有 Array,Function,Object,Promise 这些类型,将这些类型做加法是不是也可以作为很多应用场景呢?


还有另一个点就是,除了加法,我还可以做减法,甚至做 comparasion,max,min 等操作。


将上面这 3 点都用起来,不难发现单单一个 reduce 就可以有几十种玩法。下面就选几种比较典型的例子给大家一些灵感。


所有的代理(包括源码和测试代码)都放在这里:github.com/Haixiang612…


max


Python 有这样的语法:max([1, 2, 3] // => 3,JS 是没有的,使用 reduce 就可以简单地实现上面的功能:


type TComparator<T> = (a: T, b: T) => boolean
function max<T>(array: T[], largerThan?: TComparator<T>): T {
  return array.reduce((prev, curt) => {
    return largerThan(prev, curt) ? prev : curt
  })
}
export default max
复制代码


用例


describe('max', () => {
  it('返回简单元素最大值', () => {
    const array = [1, 2, 3, 4, 5]
    const result = max<number>(array, (a, b) => a > b)
    expect(result).toEqual(5)
  })
  it('返回复杂对象的最大值', () => {
    const array: TItem[] = [
      {value: 1}, {value: 2}, {value: 3}
    ]
    const result = max<TItem>(array, (a, b) => a.value > b.value)
    expect(result).toEqual({value: 3})
  })
})
复制代码


findIndex


JS 有一个 Array.indexOf 的 API,但是对于像 [{id: 2}, {id: 3}] 这样的数据结构就不行了,我们一般希望传一个回调去找对应的对象的下标。使用 reduce 可以这么写:


type TEqualCallback<T> = (item: T) => boolean
function findIndex<T>(array: T[], isEqual: TEqualCallback<T>) {
  return array.reduce((prev: number, curt, index) => {
    if (prev === -1 && isEqual(curt)) {
      return index
    } else {
      return prev
    }
  }, -1)
}
export default findIndex
复制代码


用例

describe('findIndex', () => {
  it('可以找到对应的下标', () => {
    const array: TItem[] = [
      {id: 1, value: 1},
      {id: 2, value: 2},
      {id: 3, value: 3},
    ]
    const result = findIndex<TItem>(array, (item) => item.id === 2)
    expect(result).toEqual(1)
  })
})
复制代码

filter


使用 reduce 一样可以重新实现 Array 下的一些 API,比如 filter

type TOkCallback<T> = (item: T) => boolean
function filter<T>(array: T[], isOk: TOkCallback<T>): T[] {
  return array.reduce((prev: T[], curt: T) => {
    if (isOk(curt)) {
      prev.push(curt)
    }
    return prev
  }, [])
}
export default filter
复制代码


用例

describe('filter', () => {
  it('可以过滤', () => {
    const array: TItem[] = [{id: 1}, {id: 2}, {id: 3}]
    const result = filter<TItem>(array, (item => item.id !== 1))
    expect(result).toEqual([{id: 2}, {id: 3}])
  })
})
复制代码
相关文章
|
算法
【每日一题Day349】LC260只出现一次的数字 III | 位运算
【每日一题Day349】LC260只出现一次的数字 III | 位运算
80 0
|
数据可视化 数据挖掘 BI
数据分析工具
【5月更文挑战第17天】数据分析工具
373 6
|
并行计算 JavaScript 算法
opencv4.5.1+contrib+cuda编译成功,实时人头匹配,手动狗头
这篇文章介绍了如何在Windows 10上使用Visual Studio 2017成功编译OpenCV 4.5.1及其contrib模块和CUDA支持,并解决了编译过程中的问题,如项目文件无效、cmake工具问题,并添加了Qt和JavaScript支持,同时提供了参考链接。
219 7
opencv4.5.1+contrib+cuda编译成功,实时人头匹配,手动狗头
|
网络协议 数据库 网络架构
OSPF 路由器 ID 的用途
【8月更文挑战第24天】
324 0
DHL
|
算法 安全 Java
再见吧 buildSrc, 拥抱 Composing builds 提升 Android 编译速度
长期以来困扰我们的一个问题就是构建速度,AndroidStudio 的构建速度严重影响 Android 开发者的工作效率,尤其是更新一个版本号,导致整个项目重新构建,在网络慢的情况下,这是无法忍受的。
DHL
1051 0
再见吧 buildSrc, 拥抱 Composing builds 提升 Android 编译速度
|
JSON JavaScript 数据格式
vue展示json数据,vue-json-viewer的使用
vue展示json数据,vue-json-viewer的使用
352 0
|
对象存储 机器学习/深度学习 存储
大语言模型一键转存到OSS并挂载PAI实现企业知识库
本文介绍如何实现一键转载主流的大语言模型到自己的对象存储OSS空间中,然后再挂载到PAI-DSW实现多种模型切换测试知识库的效果。
大语言模型一键转存到OSS并挂载PAI实现企业知识库
|
前端开发
CSS:设置字母间距、中文汉字间距
CSS:设置字母间距、中文汉字间距
|
SQL XML Java
Java:MyBatis实现增删改查
MyBatis是一款开源的Java持久层框架,可以将SQL语句和Java程序代码进行分离,开发者无需直接编写JDBC代码,通过XML或注解的方式配置SQL语句和映射关系,简化了数据库操作的过程。MyBatis具有良好的扩展性和灵活性,提供了多种插件和自定义类型转换器等功能,广泛应用于企业级开发中。
184 0
|
存储 Linux 调度
【Linux】基础IO_1
【Linux】基础IO_1
77 0