在 JavaScript 中计算数组的某些元素出现的次数

Pablo Felipe 2023年10月12日
  1. 在 JavaScript 中使用 .filter 方法来计数数组中的某些元素
  2. 在 JavaScript 中使用 .reduce 方法执行回调函数
  3. 在 JavaScript 中使用 .prototype 数组实体编写自定义方法或属性
在 JavaScript 中计算数组的某些元素出现的次数

介绍一下 .filter 方法,该方法可用于根据条件过滤数组元素,除了 .length 属性外,我们还可以使用它来计算数组的某些元素。函数提供 .filter 方法的条件,作为参数传递。

此外,我们将介绍 .reduce 方法,该方法为数组中的每个元素执行一个函数并返回一个值。

作为参数传递的函数可以是箭头函数,也可以是作为回调函数的普通函数。它将指示 .filter 将添加到返回数组中的元素或 .reduce 方法将对数组中的每个元素执行什么操作。

在 JavaScript 中使用 .filter 方法来计数数组中的某些元素

.filterArray 实体的一个方法,它返回一个由提供的条件过滤的新数组。返回一个新数组意味着调用该方法的原始数组将保持不变。

例如,如果我们想要数组中所有等于值 one 的元素,我们可以使用 .filter,如下所示:

// Input
let array = ['one', 'two', 'three', 'four', 'five']
array = array.filter(element => element == 'one')
console.log(array)

输出:

// Output
[ 'one' ]

正如预期的那样,.filter 方法返回了一个基于 element == 'one' 条件的数组。因此,如果数组的实际元素等于'one',则过滤器会将这个元素添加到返回的数组中。

但是 .filter 方法内部发生了什么?通过对 condition() 函数使用通用函数结构,我们可以看得更清楚:

// Input
let array = ['one', 'two', 'three', 'four', 'five']
array = array.filter(function condition(element) {
  if (element == 'one') return true
    return false
})
console.log(array)

有了这个,我们有相同的第一个示例输出:

// Output
[ 'one' ]

condition() 函数接收一个 element 作为参数,如果此 element 等于某个值,在本例中为 'one',则返回 true,否则返回错误的

因此,.filter 方法添加条件导致 true 的任何元素;由于原始数组只有第一个元素为 one,因此 .filter 仅返回一个元素。

请注意,condition() 函数是在 .filter 方法中声明的。如果你在外面声明它并在 filter 中调用它,它不会起作用,因为 element 是回调范围的一部分。

回调函数作为参数传递给另一个称为外部函数的函数。

外层函数会调用回调函数做某事;在 .filter 方法的情况下,它将调用 condition() 回调函数以根据其条件过滤数组。

回到我们的目标,.filter 最终将返回一个带有 array.length 元素的新数组,每个元素都是一个元素,其回调函数返回的值等于 true。我们可以很容易地使用 .length 属性来计算这些过滤后的元素。

.length 是数组实体的一个属性,它返回数组中元素的数量。这个数字总是大于该数组中的最高索引,因为第一个元素总是在索引上等于 0

// Input
let array = [1, 2, 3, 4, 5]
console.log(array.length)

输出:

// Output
5

array 中的元素数为 5。5 大于值 5 的索引,即 4。

综上所述,作为一个例子,我们可以使用以下内容:如何获得大于七的学校的所有测试笔记的数量?测试笔记的数组在示例中。

// Input
let notes =
    [7.0, 6.7, 7.3, 9.8, 5.6, 7.1, 7.8, 6.2, 8.0, 9.0, 4.5, 6.9, 7.5, 8.5, 6.4]
greaterThanSeven = notes.filter(value => value > 7)
console.log(greaterThanSeven.length)

输出:

// Output (The array returned by the .filter is: [7.3, 9.8, 7.1, 7.8, 8, 9, 7.5, 8.5])
8

因此,8 是原始 notes 数组中所有 15 个音符中大于 7 的音符数。

在 JavaScript 中使用 .reduce 方法执行回调函数

我们可以使用 .reduce 数组实体方法作为另一种选择。此方法用于对每个数组元素执行回调函数(和 .filter),但最终会返回一个值。

.reduce 工作的一个简单示例是数组中所有元素的总和:

// Input
let array = [1, 2, 3, 4, 5].reduce((previous, current) => previous + current)
console.log(array)

输出:

// Output
15

但是我们可以通过传递初始值以另一种方式使用此方法。在前面的例子中,我们可以看到 previous 从数组中的第一个索引元素开始,作为回调函数,这样:

/*
previous + current = result
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15 -> final result
*/

这个总和有效,因为如果我们不将第二个参数(因为回调函数是第一个参数)传递给 .reduce 方法,它将在第一次迭代中将 previous 视为数组的第一个元素。

但是如果我们想计算数组中的某些元素呢?我们不能将第一个元素用作 previous,因为它可能导致错误的值。

下面的示例是关于计算数组中有多少 2 个数字:

// Input
let array = [1, 2, 3, 4, 5].reduce((sum, value) => (value == 2 ? sum + 1 : sum))
console.log(array)

输出:

// Output
2

如我们所见,结果是 2,但正确答案是 1。发生这种情况是因为 sum 是用第一个元素 1 初始化的,因为我们没有传递回调函数之外的任何其他参数。

为了进行更正,我们可以传递一个 0 作为第二个 .reduce 参数:

// Input
let array =
    [1, 2, 3, 4, 5].reduce((sum, value) => (value == 2 ? sum + 1 : sum), 0)
console.log(array)

输出:

// Output
1

这样,每次当前元素等于 2 时,.reduce 都会产生 sum + 1,而 sum 初始化为 0

在 JavaScript 中使用 .prototype 数组实体编写自定义方法或属性

作为一个优点,我们可以使用 .prototype 数组实体属性来向该实体写入自定义方法或属性,而不是每次需要计算数组中的某些元素时都使用所有这些逻辑。

要为数组实体创建一个 .countCertainElements 方法,我们可以使用以下结构:

// Input
// Declaring the prototype .countCertainElements method
Array.prototype.countCertainElements = function(value) {
  return this.filter(arrayElement => arrayElement == value).length
} let array1 = [1, 2, 2, 2, 3, 4, 5]
console.log(array1.countCertainElements(2))

输出:

// Output
3

我们可以对 .reduce 做同样的事情:

// Input
// Declaring the prototype .countCertainElements method
Array.prototype.countCertainElements = function(value) {
  return this.reduce((sum, element) => (element == value ? sum + 1 : sum), 0)
} let array1 = [1, 2, 2, 2, 3, 4, 5]
console.log(array1.countCertainElements(2))

输出:

// Output
3

相关文章 - JavaScript Array