For 循环

一般关于实现数组的某种操作,可能最先想到的就是 for 循环吧!下面是它的实现。

let min = arr => {
  let greatest = arr[0]
  for (let i = 0; i < arr.length; i++) {
    if (greatest > arr[i]) {
      greatest = arr[i]
    }
  }
  return greatest
}

let max = arr => {
  let greatest = 0
  for (let i = 0; i < arr.length; i++) {
    if (greatest < arr[i]) {
      greatest = arr[i]
    }
  }
  return greatest
}

console.log(max(arr)) // 25
console.log(min(arr)) // 1

Math.min()/max()

内置函数 Math.max()Math.min() 可以分别返回一直数中的最大值和最小值,其可以接受任意数量的参数。

Math.max(25, 5, 15, 6, 9, 1, 3) // 25
Math.min(25, 5, 15, 6, 9, 1, 3) // 1

这很方便,但它不能直接用于数组。我们需要一些其他的方法来帮助我们使用它。

call/apply

Function.prototype.apply() 方法调用一个具有给定this值的函数,以及以一个数组的形式提供的参数。

Function.prototype.call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

  • apply() 第二个参数传递 arr 数组,使用数组中的所有值作为函数的参数。
  • call() 第二个参数传递 arr 数组,并使用扩展运算符,将其展开作为其函数的参数。
let max = arr => Math.max.apply(null, arr)
let min = arr => Math.min.call(null, ...arr)

console.log(max(arr)) // 25
console.log(min(arr)) // 1

扩展运算符

更为简单的方式是,直接使用 ES6 的扩展运算符(...)展开数组。

console.log(Math.max(...arr)) // 25
console.log(Math.min(...arr)) // 1

Array.prototype.sort()

使用 Array.prototype.sort 先对数组进行排序,在获取数组的第一个元素。

let arr = [25, 5, 15, 6, 9, 1, 3]

let max = arr => arr.sort((a, b) => b - a)[0]
let min = arr => arr.sort((a, b) => a - b)[0]

console.log(max(arr)) // 25
console.log(min(arr)) // 1

如果你还不熟,可以看看 如何在 JavaScript 中对对象数组进行排序?了解 sort() 的用法。

任意数量的最大值

从提供的数组返回 n 个最大元素。

  • 使用 Array.prototype.sort() 和扩展运算符(...)配合,创建数组的浅拷贝,并按降序排序。
  • 使用 Array.prototype.slice() 获取指定数量的元素。
  • 省略第二个参数 n,得到一个单元素数组。
  • 如果 n 大于或等于提供的数组长度,则返回原始数组(按降序排序)。
const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n)

maxN([25, 5, 15, 6, 9, 1, 3]) // [25]
maxN([25, 5, 15, 6, 9, 1, 3], 3) // [25, 15, 9]

任意数量的最小值

从提供的数组返回 n 个最小元素。

  • 使用 Array.prototype.sort() 和扩展运算符(...)配合,创建数组的浅拷贝,并按升序排序。
  • 使用 Array.prototype.slice() 获取指定数量的元素。
  • 省略第二个参数 n,得到一个单元素数组。
  • 如果 n 大于或等于提供的数组长度,则返回原始数组(按升序排序)。
const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n)

minN([25, 5, 15, 6, 9, 1, 3]) // [1]
minN([25, 5, 15, 6, 9, 1, 3], 3) // [1, 3, 5]

这两个示例来自 30 seconds of code 的 maxNminN

复杂情况 — 对象数组

对于更复杂的情况(即在对象数组中查找最小/最大值),您可能需要使用 Array.prototype.map() 等一些方法。

最小值

使用提供的函数将每个元素映射到一个值后,返回数组的最小值。

  • 使用 Array.prototype.map() 将每个元素映射到 fn 所返回的值。
  • 使用 Math.min() 获得的最小- 值。
const minBy = (arr, fn) =>
  Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]))

minBy([{ n: 4 }, { id: 2 }, { id: 8 }, { id: 6 }], x => x.id) // 2
minBy([{ id: 4 }, { id: 2 }, { id: 8 }, { id: 6 }], 'id') // 2

最大值

使用提供的函数将每个元素映射到一个值后,返回数组的最大值。

  • 使用 Array.prototype.map() 将每个元素映射到 fn 所返回的值。
  • 使用 Math.max() 获取最大值。
const maxBy = (arr, fn) =>
  Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]))

maxBy([{ id: 4 }, { id: 2 }, { id: 8 }, { id: 6 }], x => x.id) // 8
maxBy([{ id: 4 }, { id: 2 }, { id: 8 }, { id: 6 }], 'id') // 8

这两个示例来自 30 seconds of code 的 min-bymax-by