文章目录
💯前言
- 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>
解法分析
- 首先定义了一个数组
arr
,它包含 1 到 10 的整数。 - 然后通过一个
for
循环遍历整个数组,将每个元素累加到变量sum
中。 - 最后通过
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
循环遍历数组,分别查找出最大值和最小值,将它们赋值给变量 max
和 min
。该方法对于初学者来说非常合适,展示了如何遍历数组并对每个元素进行比较。
优化后的解法
记录最大值和最小值的索引
在原始解法中,只输出了最大值和最小值,但并没有找到它们的位置。以下代码对其进行了改进,增加了索引的记录:
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.max
和 Math.min
使用 JavaScript 的内置函数 Math.max
和 Math.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.max
和 Math.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()
可以在保持原数组不变的情况下得到反转结果。
💯双指针方法详解
在数组反转问题中,使用双指针是一种经典的技巧。
什么是双指针?
双指针是一种编程技巧,尤其在处理数组和链表时非常常见。在这个方法中,使用两个指针从不同的位置开始遍历数据结构,直到它们相遇。具体来说:
- 左指针:从数组的开头向右移动。
- 右指针:从数组的末尾向左移动。
在每次迭代中,左右指针所指向的元素会被交换,然后指针向中间移动,直到相遇为止。
使用双指针的优势
- 时间复杂度:双指针法的时间复杂度是
O(n)
,因为它只需要遍历数组的一半。 - 空间复杂度:该方法的空间复杂度是
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;
}
- 初始化指针:左指针
i
从0
开始,右指针arr.length - 1 - i
从数组末尾开始。 - 交换元素:用一个临时变量
temp
保存左指针的值,然后交换左右指针对应的值。 - 停止条件:当左指针和右指针相遇或交叉时(即
i >= arr.length / 2
),数组就已经完全反转。
双指针方法是非常经典和高效的实现方式,在算法面试和开发中常常用于处理类似对称的操作,例如判断回文字符串。
💯小结
通过这些例题,我们不仅学会了如何实现这些常见的操作,还了解了如何利用 JavaScript 中的内置方法和现代编程风格使代码更加简洁、易读和高效。在实际开发中,我们应该选择最适合当前场景的实现方式,综合考虑代码的性能、可读性和维护性。