如何计算JavaScript数组中的元素出现次数

1,896 阅读5分钟

简介

在JavaScript中使用数组时,我们经常会遇到需要计算数组中某个特定元素出现次数的情况,这个元素可以是字符串、对象、数字,甚至是布尔值。

在这篇文章中,我们将介绍几种方法来计算一个元素或JavaScript数组中所有元素的出现次数。我们还将看看如何通过先将数组扁平化来计算数组中的元素出现次数。

如何使用循环来计算元素的出现次数

for 循环是在一个数组中进行循环的标准方法之一。它允许我们循环数组中的每个元素,并将其与我们正在寻找的元素进行比较。这样,我们就可以计算该元素在数组中出现的次数。我们也可以用它来计算数组中所有元素的出现次数,但我们将在本文的后面介绍这种情况。现在,让我们假设我们想找到特定元素的出现次数。

最佳解决方案:for-of循环

显然,JavaScript有一个内置的for 循环,我们可以使用,但是,为了使事情更简单,我们可以使用它的修改版--for-of 循环。这样,我们就不用通过数组中的索引来访问每个元素,而可以访问元素本身的值。

注意:JavaScript ES2015引入了for-of 循环。它是array.forEach() 方法的替代品,以前用于遍历数组中的每个元素,并对每个元素进行一些修改。for-offorEach() 的主要区别是,前者与async 函数兼容。在这篇文章中,我们选择主要使用for-of 循环,而不是forEach() 方法,只是为了在异步情况下安全,但如果你不屑于此,可以随意使用forEach() 来代替!

首先,让我们看看一个特定的元素在一个数组中出现了多少次。为了达到这个目的,我们需要将counter 变量设置为0 ,然后在数组中循环,每找到一个我们要找的元素,就将counter 增加一次。当我们在整个数组中循环时,counter 将存储我们正在寻找的元素的出现次数。

const allStudentsAge = [19, 22, 18, 19, 16, 18, 19, 21, 24];
let target = 19;

let counter = 0;
for (studentAge of allStudentsAge) {
  if (studentAge == target) {
        counter++;
    }
};

console.log(counter); // 3

如果我们有一个数组的数组,情况就比较复杂了。在这种情况下,我们首先要把数组扁平化,使所有的元素都进入一个数组,使用flat() 方法。

const allStudentsAge = [
    [1, 19],
    [3, 4],
    [5, 19],
    [7, 8, 19],
    [10, 11, 12, 13, 14, 15],
    [19, 22, 18, 19, 16, 18, 19, 21, 24]
];

let target = 19;

let counter = 0;
for (studentAge of allStudentsAge.flat()) {
  if (studentAge == target) {
        counter++;
    }
};

console.log(counter); // 6

这也适用于具有不同数据类型的元素的数组。让我们创建一个具有不同数据类型的数组实例,并检查一下我们是否可以计算某个元素的出现次数。

const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

现在,我们可以创建一个可重复使用的函数,计算给定数组中给定元素的出现次数。

const checkOccurrence = (array, element) => {
    let counter = 0;
    for (item of array.flat()) {
        if (item == element) {
            counter++;
        }
    };
    console.log(counter);
};

让我们检查一下我们所创建的函数是否真的有效。

checkOccurrence(myArray, false); // 3
checkOccurrence(myArray, 19); // 2
checkOccurrence(myArray, "english"); // 1

我们已经验证了元素false 有三个实例,元素19 有两个实例,这是正确的,但是为什么元素"english" 只出现了一个,而不是三个?这是由于我们创建的函数的大小写敏感性造成的--解决这个问题的最好方法是在计数前将所有字符串元素转换为大写(或小写)。

const checkOccurrence = (array, element) => {
    let counter = 0;
    for (item of array.flat()) {
        if (typeof item === "string") {
            let newItem = item.toLowerCase();
            if (newItem == element) {
                counter++;
            }
        } else {
            if (item == element) {
                counter++;
            }
        }
    };
    console.log(counter);
};

当我们现在计算元素"english" 的出现次数时,checkOccurrence() 函数返回3 ,因为它不再对大小写敏感。

checkOccurrence(myArray, "english"); // 3

替代方案#1:for循环

如果你因为某些原因需要访问数组中每个元素的索引,你也可以使用基本的for 循环来代替for-of

const checkOccurrence = (array, element) => {
    let counter = 0;
    for (let i = 0; i <= array.length; i++) {
        if (array[i] == element) {
            counter++;
        }
    }
    console.log(counter);
};

我们可以检查一下,这与用for-of 循环创建的相同函数得到的结果是一样的。

checkOccurrence(myArray, false); // 3
checkOccurrence(myArray, 19); // 2
checkOccurrence(myArray, "english"); // 1

替代方案#2:*forEach()*方法

另一个可行的替代方法是使用forEach() 方法来遍历一个数组的所有元素。

const checkOccurrence = (array, element) => {
    let counter = 0;
    array.forEach()for (let i = 0; i <= array.length; i++) {
        if (array[i] == element) {
            counter++;
        }
    }
    console.log(counter);
};

这将使我们得到与前面的函数相同的结果,但是,同样,在异步环境中使用forEach() 方法时要小心。

checkOccurrence(myArray, false); // 3
checkOccurrence(myArray, 19); // 2
checkOccurrence(myArray, "english"); // 1

检查所有元素的出现次数

到目前为止,我们已经看到如何计算一个特定元素的出现次数。现在,让我们看看如何计算所有元素的出现次数,并将元素和出现次数作为一个对象返回。

首先,我们将创建一个空对象来存储每个数组元素作为键,并将出现次数作为值。然后,我们将使用for-of 循环遍历数组,在每次迭代中,如果对象中已经存在特定的元素,我们将增加该元素的计数,否则将计数设置为1

const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

let counter = {};
for (element of myArray.flat()) {
    if (counter[element]) {
        counter[element] += 1;
    } else {
        counter[element] = 1;
    }
};
console.log(counter);

前面的代码将输出包含每个元素在myArray 中出现的次数的对象。

{
    "19": 2,
    "22": 1,
    "24": 1,
    "English": 2,
    "english": 1,
    "false": 3
}

假设我们仍然想避免大小写敏感,我们可以这样做。

const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

let counter = {};
for (element of myArray.flat()) {
    if (typeof element === "string") {
        let newItem = element.toLowerCase();
        if (counter[newItem]) {
            counter[newItem] += 1;
        } else {
            counter[newItem] = 1;
        }
    } else {
        if (counter[element]) {
            counter[element] += 1;
        } else {
            counter[element] = 1;
        }
    }
});
console.log(counter);

这将输出下面这个对象。

{
    "19": 2,
    "22": 1,
    "24": 1,
    "false": 3,
    "english": 3
}

如何使用reduce()来计算元素的出现次数

reduce() 是一个强大的方法,只需几行代码就可以轻松获得一个数组中每个元素的出现次数。它接受一个回调函数和一个初始值,对我们来说,它是一个空对象,以便我们以后可以填充它。

const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

let countObject = myArray.reduce(function (
    count,
    currentValue
) {
    return (
        count[currentValue] ? ++count[currentValue] : (count[currentValue] = 1),
        count
    );
},
{});

console.log(countObject);

这将输出一个对象,包含作为键的元素和作为值的出现次数。

{
    "19": 2,
    "22": 1,
    "24": 1,
    "false": 3,
    "English": 2,
    "english": 1
}

如何使用filter()方法来计算元素的出现次数

在上一节中,我们看到了如何使用循环和reduce() 方法来处理我们可能想要计算JavaScript数组中的元素出现次数的各种情况。除了循环和reduce() ,我们还可以使用其他方法,比如filter() ,来确定一个数组中特定元素的出现次数。

为了达到这个目的,我们将对其进行过滤,然后根据条件填充一个数组,我们将使用length 属性从中获得长度。

const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

const itemCounter = (array, item) => {
    return array.filter((currentItem) => currentItem == item).length;
};

console.log(itemCounter(myArray, 19)); // 2

使用Lodash来计算元素的出现次数

最好不要为了计算数组中的元素而安装额外的包,但是如果我们已经在项目中使用了Lodash库,那么使用它来计算元素也无妨。Lodash的.countBy() 方法接受一个数组并返回一个对象。这个对象包含元素和它们的计数,是键值对。

const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

let lodash = _;
let elementOccurrences = _.countBy(myArray);
console.log(elementOccurrences);

这将给我们一个对象。

{
    "19": 2,
    "22": 1,
    "24": 1,
    "false": 3,
    "English": 2,
    "english": 1
}

结论

如果你需要计算一个数组中元素的出现次数,可能你最好的选择是使用本文中所示的for-of 循环。它是async ,但仍然是一个非常简单的方法来迭代整个数组并计算所需元素。我们也看了一下其他的替代方法--基本的for 循环,forEach() ,和filter() 方法。

如果你需要看一下每个元素在数组中出现的次数,我们也已经帮你解决了 - 你可以再次使用for-of 循环。此外,你还可以使用reduce() 方法,或者Lodash库。