Bootstrap

【前端】JavaScript 中数组的基本操作及优化题解


在这里插入图片描述

博客主页: [小ᶻZ࿆]
本文专栏: 前端


在这里插入图片描述


💯前言

  • JavaScript 是一种强大而灵活的编程语言,在 Web 开发中得到了广泛应用。学习数组的基本操作是编程入门的重要一步。在这篇文章中,我们将讨论三道关于数组的基础题目,分别涉及数组求和、最大最小值查找以及数组连接的操作。我们不仅会讲解这些题目的基础解法,还会给出优化后的版本,并探讨代码扩展和实现背后的思路,帮助你更深入地理解 JavaScript 的数组操作。希望通过这篇文章,大家能更好地掌握数组的相关知识和技能。
    JavaScript
    在这里插入图片描述

💯题目一:求一数组中的所有数的和和平均值

在这里插入图片描述


最初的解法

在这里插入图片描述

首先来看一道基础的题目,题目要求我们对数组中的所有数进行求和,然后计算出数组的平均值。以下是原题目以及初始解法:

<body>
    <script>
        var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var sum = 0;
        for (var i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        console.log("和: " + sum);
        console.log("平均值为: " + (sum / arr.length));
    </script>
</body>

解法分析

  1. 首先定义了一个数组 arr,它包含 1 到 10 的整数。
  2. 然后通过一个 for 循环遍历整个数组,将每个元素累加到变量 sum 中。
  3. 最后通过 console.log 输出求和的结果和计算平均值。

这是非常基础且常用的方法,代码简单明了,适合入门者理解循环和数组的基本操作。


优化后的解法

在这里插入图片描述


使用 Array.prototype.reduce 方法

在这里插入图片描述

JavaScript 提供了一些高效的数组方法,比如 reduce,它可以用来累加数组中的所有元素,使代码更简洁。

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var sum = arr.reduce((acc, current) => acc + current, 0);
console.log("和: " + sum);
console.log("平均值为: " + (sum / arr.length));

使用箭头函数和模板字符串

在这里插入图片描述

使用箭头函数和模板字符串可以让代码更现代化,增加可读性和简洁性:

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const sum = arr.reduce((a, b) => a + b, 0);
console.log(`和: ${sum}`);
console.log(`平均值为: ${sum / arr.length}`);

扩展:封装成函数

在这里插入图片描述

对于程序模块化的学习,我们可以把这些操作封装成一个函数,使其具有更好的复用性和扩展性:

function calculateSumAndAverage(arr) {
    var sum = arr.reduce((a, b) => a + b, 0);
    var average = sum / arr.length;
    return { sum, average };
}

var result = calculateSumAndAverage([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
console.log("和: " + result.sum);
console.log("平均值为: " + result.average);

通过将求和和平均值的逻辑封装成一个函数,代码的复用性得到了极大的提升。如果数组发生变化,只需要调用函数即可,极大减少了代码的重复。模块化的编程方式是编写大规模应用的基础。


💯题目二:求一数组中的最大值和最小值,以及所在位置

在这里插入图片描述


最初的解法

在这里插入图片描述

第二道题目是找到数组中的最大值和最小值,同时输出它们在数组中的位置。以下是最初的实现:

<script>
    var arr = [7, 6, 3, 2, 4, 9, 1, 8, 5, 10];
    var max = arr[0];
    var min = arr[0];
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] < min) {
            min = arr[i];
        }
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    console.log("最大值为: " + max);
    console.log("最小值为: " + min);
</script>

解法分析

这个解法通过 for 循环遍历数组,分别查找出最大值和最小值,将它们赋值给变量 maxmin。该方法对于初学者来说非常合适,展示了如何遍历数组并对每个元素进行比较。


优化后的解法

在这里插入图片描述


记录最大值和最小值的索引

在这里插入图片描述

在原始解法中,只输出了最大值和最小值,但并没有找到它们的位置。以下代码对其进行了改进,增加了索引的记录:

var arr = [7, 6, 3, 2, 4, 9, 1, 8, 5, 10];
var max = arr[0], min = arr[0];
var maxIndex = 0, minIndex = 0;

for (var i = 1; i < arr.length; i++) { // 从索引 1 开始,因为索引 0 已经初始化了
    if (arr[i] > max) {
        max = arr[i];
        maxIndex = i;
    }
    if (arr[i] < min) {
        min = arr[i];
        minIndex = i;
    }
}

console.log("最大值: " + max + ", 位置: " + maxIndex);
console.log("最小值: " + min + ", 位置: " + minIndex);

使用 Math.maxMath.min

在这里插入图片描述

使用 JavaScript 的内置函数 Math.maxMath.min 可以更快速地找到数组中的最大值和最小值,然后通过 indexOf 获取它们的索引。

var arr = [7, 6, 3, 2, 4, 9, 1, 8, 5, 10];
var max = Math.max(...arr);
var min = Math.min(...arr);

var maxIndex = arr.indexOf(max);
var minIndex = arr.indexOf(min);

console.log("最大值: " + max + ", 位置: " + maxIndex);
console.log("最小值: " + min + ", 位置: " + minIndex);

Math.maxMath.min 使用扩展运算符 ... 来将数组的元素作为参数传递,使代码更简洁。


扩展:封装成函数

在这里插入图片描述

同样地,我们可以将查找最大值、最小值及其位置的逻辑封装成函数:

function findMaxAndMin(arr) {
    var max = arr[0], min = arr[0];
    var maxIndex = 0, minIndex = 0;

    for (var i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
            maxIndex = i;
        }
        if (arr[i] < min) {
            min = arr[i];
            minIndex = i;
        }
    }

    return { max, min, maxIndex, minIndex };
}

var arr = [7, 6, 3, 2, 4, 9, 1, 8, 5, 10];
var result = findMaxAndMin(arr);

console.log("最大值: " + result.max + ", 位置: " + result.maxIndex);
console.log("最小值: " + result.min + ", 位置: " + result.minIndex);

💯题目三:将字符串数组用|或其他符号拼接

在这里插入图片描述


最初的解法

在这里插入图片描述

第三道题目要求我们将数组中的元素用指定的符号连接起来。以下是初始的实现:

<body>
    <script>
        var arr = [7, 6, 3, 2, 4, 9, 1, 8, 5, 10];
        var arr2 = arr.join("-");
        console.log(arr2);
    </script>
</body>

解法分析

在这段代码中,我们使用了 Array.prototype.join 方法来将数组中的元素用 - 连接起来,形成一个字符串并输出。join 方法是数组操作中非常高效且方便的方法。


优化与扩展

在这里插入图片描述


使用变量定义分隔符

在这里插入图片描述

为了让代码更加灵活,我们可以定义一个变量来存储分隔符,这样在需要更换分隔符的时候只需更改变量的值即可,代码更易于维护:

var arr = [7, 6, 3, 2, 4, 9, 1, 8, 5, 10];
var separator = "-"; // 定义分隔符
var arr2 = arr.join(separator);
console.log(arr2);

扩展功能:用户自定义输入分隔符

在这里插入图片描述

如果希望增强用户交互性,可以通过浏览器的 prompt 函数来让用户输入分隔符,从而实现动态控制:

// 用户输入分隔符
var separator = prompt("请输入分隔符(例如 '-' 或 '|'):", "-");

// 示例数组
var arr = [7, 6, 3, 2, 4, 9, 1, 8, 5, 10];

// 用 join 方法处理
var arr2 = arr.join(separator);

// 输出结果
console.log(arr2);

扩展:处理多维数组

在这里插入图片描述

在更复杂的场景下,我们可能会遇到多维数组,需要先将其展平,再用特定符号连接。可以使用 Array.prototype.flat() 方法来展平多维数组:

var arr = [[7, 6], [3, 2], [4, 9, 1, 8], [5, 10]];
var separator = "-";

// 展平数组并用分隔符连接
var arr2 = arr.flat().join(separator);

console.log(arr2); // 输出 "7-6-3-2-4-9-1-8-5-10"

在这个示例中,flat() 方法将二维数组展平成一维,然后使用 join() 方法将元素连接在一起。


封装成函数

在这里插入图片描述

将连接数组元素的逻辑封装成一个通用函数:

function joinArrayElements(arr, separator) {
    return arr.flat().join(separator);
}

var arr = [[7, 6], [3, 2], [4, 9, 1, 8], [5, 10]];
var result = joinArrayElements(arr, "|");
console.log(result); // 输出 "7|6|3|2|4|9|1|8|5|10"

封装后的函数可以处理多维数组并指定分隔符,使其在不同场景下更具有适应性。


💯题目四:要求将数组中的0项去掉,将不为0的值存入一个新的数组,生成新的数组

在这里插入图片描述


最初的解法

在这里插入图片描述

以下是使用 for 循环遍历数组并手动移除 0 的实现:

var arr1 = [0, 6, 3, 0, 4, 0, 1, 8, 0, 10];
var arr2 = [];
for (var i = 0; i < arr1.length; i++) {
    if (arr1[i] !== 0) {
        arr2.push(arr1[i]);
    }
}
console.log(arr2);

这种方法通过遍历数组,将所有不为 0 的元素加入新数组 arr2 中。这段代码逻辑正确并且相对直观,但稍显冗长且不够现代化。


优化解法

在这里插入图片描述


使用 Array.filter() 方法

在这里插入图片描述

JavaScript 提供了 filter() 方法,可以对数组中的元素进行条件筛选,从而使代码更加简洁和直观:

var arr1 = [0, 6, 3, 0, 4, 0, 1, 8, 0, 10];
var arr2 = arr1.filter(item => item !== 0);
console.log(arr2);

在这段代码中,filter() 方法会遍历整个数组,将每个元素传入回调函数,如果元素满足条件(即不等于 0),则保留该元素,形成新的数组。这样一来,我们不仅实现了同样的功能,还使代码更加易读和简洁。


使用 Array.reduce() 方法

在这里插入图片描述

我们还可以使用 reduce() 方法来实现相同的效果:

var arr1 = [0, 6, 3, 0, 4, 0, 1, 8, 0, 10];
var arr2 = arr1.reduce((acc, curr) => {
    if (curr !== 0) acc.push(curr);
    return acc;
}, []);
console.log(arr2);

这里的 reduce() 方法用于遍历数组并将不为 0 的元素累加到一个新的数组中,最终返回结果。虽然代码略显复杂,但这种方式展示了 reduce() 的灵活性和强大功能。


思路总结

在这里插入图片描述

  • 使用 for 循环的方式适合对 JavaScript 语法不熟悉的初学者,因为逻辑显式且清晰。
  • 使用 filter() 可以简化代码,更加现代化并提高可读性,适合在开发中使用。
  • 使用 reduce() 则适合需要展示 JavaScript 高级技巧的场景。

💯题目五:查找数组[1,2,3,4,1,2,3,4,2,3,1,1,0]中所有值为1的项的下标 输出为新数组

在这里插入图片描述


最初的解法

在这里插入图片描述

以下是使用 for 循环实现的代码:

var arr = [1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 1, 1, 0];
var arr2 = [];
for (var i = 0; i < arr.length; i++) {
    if (arr[i] == 1) {
        arr2.push(i);
    }
}
console.log(arr2);

这段代码逻辑清晰,通过遍历数组找到所有值为 1 的项,并将它们的下标添加到 arr2 中。


优化解法


使用 Array.forEach() 方法

我们可以使用 forEach() 方法来使代码更加简洁:

var arr = [1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 1, 1, 0];
var arr2 = [];
arr.forEach((value, index) => {
    if (value === 1) {
        arr2.push(index);
    }
});
console.log(arr2);

forEach() 方法让我们不再需要显式管理循环变量 i,直接通过回调函数处理每个元素和它的下标。


使用 Array.reduce() 方法

使用 reduce() 也是一种实现方式:

var arr = [1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 1, 1, 0];
var arr2 = arr.reduce((acc, value, index) => {
    if (value === 1) {
        acc.push(index);
    }
    return acc;
}, []);
console.log(arr2);

通过 reduce() 方法,我们将值为 1 的项的下标累积到 acc 中,最终返回结果。


使用 Array.map()Array.filter() 方法

我们还可以结合 map()filter() 方法:

var arr = [1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 1, 1, 0];
var arr2 = arr.map((_, index) => index).filter(index => arr[index] === 1);
console.log(arr2);

这里先通过 map() 方法生成所有索引,然后使用 filter() 筛选出对应值为 1 的索引。这样也可以避免显式管理循环变量,使代码更加简洁。


思路总结

  • 使用 for 循环适合初学者和需要显式控制遍历过程的场景。
  • forEach() 方法让代码更为现代化,同时简化了循环逻辑。
  • reduce()map() + filter() 提供了更加灵活和功能强大的实现方式。

💯题目六:翻转数组 [1,2,3,4,5] => [5,4,3,2,1]


最初的解法

以下是使用 for 循环实现的代码:

var arr = [1, 2, 3, 4, 5];
for (var i = 0; i < (arr.length / 2); i++) {
    var temp = 0;
    temp = arr[i];
    arr[i] = arr[arr.length - 1 - i];
    arr[arr.length - 1 - i] = temp;
}
console.log(arr);

这段代码使用了双指针方法,交换数组的两端元素,直到中点,从而完成数组反转。


优化解法

在这里插入图片描述


使用 Array.reverse() 方法

在这里插入图片描述

JavaScript 提供了内置的 reverse() 方法,可以简洁地实现数组反转:

var arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr);

reverse() 方法是最直接和简洁的方式,代码更加易读。


使用扩展运算符和 reverse()

在这里插入图片描述

如果需要保留原数组并返回反转后的新数组,可以使用扩展运算符:

var arr = [1, 2, 3, 4, 5];
var reversedArr = [...arr].reverse();
console.log(reversedArr);

这样可以避免直接修改原数组,使代码更加灵活。


使用 for 循环不改变原数组

在这里插入图片描述

如果你想手动实现反转,但不想改变原数组,可以这样写:

var arr = [1, 2, 3, 4, 5];
var reversedArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
    reversedArr.push(arr[i]);
}
console.log(reversedArr);

这种方式与原代码的思路类似,但通过反向遍历的方式创建了一个新数组,避免了对原数组的修改。


思路总结

在这里插入图片描述

  • 双指针法适合在面试或需要手动实现反转逻辑的场景,展现了对算法的理解。
  • 使用 Array.reverse() 是最简洁的方式,适合日常开发中使用,快速达成目标。
  • 使用扩展运算符和 reverse() 可以在保持原数组不变的情况下得到反转结果。

💯双指针方法详解

在这里插入图片描述

在数组反转问题中,使用双指针是一种经典的技巧。


什么是双指针?

在这里插入图片描述

双指针是一种编程技巧,尤其在处理数组和链表时非常常见。在这个方法中,使用两个指针从不同的位置开始遍历数据结构,直到它们相遇。具体来说:

  • 左指针:从数组的开头向右移动。
  • 右指针:从数组的末尾向左移动。

在每次迭代中,左右指针所指向的元素会被交换,然后指针向中间移动,直到相遇为止。


使用双指针的优势

在这里插入图片描述

  1. 时间复杂度:双指针法的时间复杂度是 O(n),因为它只需要遍历数组的一半。
  2. 空间复杂度:该方法的空间复杂度是 O(1),因为只使用了常量空间(一个临时变量 temp),因此没有额外的内存消耗。

代码实现

在这里插入图片描述

在上面的原始解法中,双指针的操作如下:

for (var i = 0; i < (arr.length / 2); i++) {
    var temp = arr[i];
    arr[i] = arr[arr.length - 1 - i];
    arr[arr.length - 1 - i] = temp;
}
  • 初始化指针:左指针 i0 开始,右指针 arr.length - 1 - i 从数组末尾开始。
  • 交换元素:用一个临时变量 temp 保存左指针的值,然后交换左右指针对应的值。
  • 停止条件:当左指针和右指针相遇或交叉时(即 i >= arr.length / 2),数组就已经完全反转。

双指针方法是非常经典和高效的实现方式,在算法面试和开发中常常用于处理类似对称的操作,例如判断回文字符串。


💯小结

  • 在这里插入图片描述
    通过这些例题,我们不仅学会了如何实现这些常见的操作,还了解了如何利用 JavaScript 中的内置方法和现代编程风格使代码更加简洁、易读和高效。在实际开发中,我们应该选择最适合当前场景的实现方式,综合考虑代码的性能、可读性和维护性。

在这里插入图片描述


;