JavaScript 第5章:数组与迭代

news2024/10/12 2:17:46

JavaScript中的数组是一种非常实用的数据结构,它可以存储任意类型的值。下面将详细介绍数组的操作和常用的数组方法。

1. 数组声明与初始化

数组可以通过多种方式进行声明和初始化。

// 方式一:使用数组字面量
let numbers = [1, 2, 3];

// 方式二:使用Array构造函数
let emptyArray = new Array();
let arrayWithValues = new Array(1, 2, 3);

// 方式三:动态长度数组
let dynamicArray = new Array(5); // 创建一个长度为5的空数组
dynamicArray[0] = 'a';
dynamicArray[1] = 'b';

2. 数组方法

常用的数组方法
  • push(): 在数组末尾添加一个或多个元素,并返回新的数组长度。
  • pop(): 移除数组最后一个元素,并返回该元素。
  • shift(): 移除数组的第一个元素,并返回该元素。
  • unshift(): 在数组开始处添加一个或多个元素,并返回新的数组长度。
  • splice(): 用于添加/删除项目。第一个参数指定开始位置,第二个参数指定要移除的元素数量,之后的参数是要插入的元素列表。
let array = [1, 2, 3];
array.push(4); // array is now [1, 2, 3, 4]
array.pop(); // array is now [1, 2, 3], returns 4
array.shift(); // array is now [2, 3], returns 1
array.unshift(0); // array is now [0, 2, 3]
array.splice(1, 1); // array is now [0, 3], removes the second element

3. 数组迭代

常见的迭代方法
  • forEach(): 对数组中的每个元素执行提供的函数。
  • map(): 创建一个新数组,其结果是该数组中的每个元素都调用了提供的函数。
  • filter(): 创建一个新数组,包含通过测试提供的函数的所有元素。
  • reduce(): 对数组中的每个元素执行一个由您提供的“归约函数”,最终返回单个值。
let numbers = [1, 2, 3, 4, 5];

numbers.forEach((num, index) => {
    console.log(`Number at index ${index}: ${num}`);
});

let squares = numbers.map(num => num * num);
console.log(squares); // 输出: [1, 4, 9, 16, 25]

let evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // 输出: [2, 4]

let sum = numbers.reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 输出: 15

4. 实战案例:数组操作练习

案例一:筛选偶数并计算平方

假设有一个数组,我们需要筛选出所有的偶数,并计算它们的平方。

function squareEvenNumbers(numbers) {
    return numbers
        .filter(num => num % 2 === 0)
        .map(num => num * num);
}

let input = [1, 2, 3, 4, 5, 6];
let output = squareEvenNumbers(input);
console.log(output); // 输出: [4, 16, 36]
案例二:字符串数组转数字数组

给定一个字符串数组,转换成数字数组,并对每个数字加1。

function stringToNumberAndIncrement(strings) {
    return strings.map(str => parseInt(str, 10) + 1);
}

let stringNumbers = ['1', '2', '3'];
let incrementedNumbers = stringToNumberAndIncrement(stringNumbers);
console.log(incrementedNumbers); // 输出: [2, 3, 4]
案例三:统计数组中每个字符出现的次数

给定一个字符串数组,统计每个字符出现的次数。

function countCharacters(strings) {
    let counts = {};
    strings.forEach(str => {
        for (let char of str) {
            counts[char] = (counts[char] || 0) + 1;
        }
    });
    return counts;
}

let words = ['hello', 'world'];
let charCounts = countCharacters(words);
console.log(charCounts); // 输出: { h: 1, e: 1, l: 3, o: 2, w: 1, r: 1, d: 1 }

通过这些案例,我们可以看到JavaScript数组方法的强大功能,以及它们在处理数组数据时的灵活性和效率。掌握这些方法将大大提高你在处理数组时的能力。

接下来我们继续探讨JavaScript数组的更多操作和实战案例。

更多数组方法

1. 查找与比较
  • find(): 返回数组中满足提供的测试函数的第一个元素的值。
  • findIndex(): 返回数组中满足提供的测试函数的第一个元素的索引。
let users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
    { id: 3, name: 'Charlie' }
];

let user = users.find(user => user.id === 2);
console.log(user); // 输出: { id: 2, name: 'Bob' }

let index = users.findIndex(user => user.name === 'Charlie');
console.log(index); // 输出: 2
2. 排序与反转
  • sort(): 排序数组元素,默认按字符串的Unicode顺序排序。
  • reverse(): 反转数组元素的顺序。
let numbers = [3, 1, 4, 1, 5, 9, 2, 6];
numbers.sort(); // 默认按字符串排序,结果可能不是数字上的升序
console.log(numbers); // 输出: [1, 1, 2, 3, 4, 5, 6, 9] 或者其他顺序

numbers.sort((a, b) => a - b); // 数字升序排序
console.log(numbers); // 输出: [1, 1, 2, 3, 4, 5, 6, 9]

numbers.reverse(); // 反转数组
console.log(numbers); // 输出: [9, 6, 5, 4, 3, 2, 1, 1]
3. 组合与分割
  • concat(): 将两个或多个数组合并成一个新的数组。
  • slice(): 返回数组的一部分浅拷贝,不改变原数组。
let a = [1, 2];
let b = [3, 4];
let c = a.concat(b);
console.log(c); // 输出: [1, 2, 3, 4]

let slice = a.slice(0, 1); // 获取从索引0开始的一个元素
console.log(slice); // 输出: [1]
4. 填充与重复
  • fill(): 使用指定的值填充数组的一部分或全部。
  • repeat(): (不是数组方法,而是字符串方法,但可以用于数组)创建一个重复的字符串。
let zeros = new Array(5).fill(0);
console.log(zeros); // 输出: [0, 0, 0, 0, 0]

let repeatString = 'abc'.repeat(3);
console.log(repeatString); // 输出: 'abcabcabc'

实战案例:复杂数组操作

案例四:提取数组中的唯一值

给定一个数组,从中提取唯一的值,并保持原来的顺序。

function uniqueValues(array) {
    let seen = new Set();
    return array.filter(item => {
        if (!seen.has(item)) {
            seen.add(item);
            return true;
        }
        return false;
    });
}

let items = [1, 2, 2, 3, 4, 4, 4, 5];
let uniqueItems = uniqueValues(items);
console.log(uniqueItems); // 输出: [1, 2, 3, 4, 5]
案例五:数组扁平化

给定一个多维数组,将其扁平化为一维数组。

function flattenArray(array) {
    return array.reduce((acc, val) => 
        Array.isArray(val) ? acc.concat(flattenArray(val)) : acc.concat(val), []);
}

let nestedArray = [1, [2, [3, 4], 5], 6];
let flatArray = flattenArray(nestedArray);
console.log(flatArray); // 输出: [1, 2, 3, 4, 5, 6]
案例六:数组分组

给定一个数组和一个分组条件,根据条件将数组分组成对象。

function groupBy(array, keyGetter) {
    return array.reduce((accumulator, currentValue) => {
        const key = keyGetter(currentValue);
        if (!accumulator[key]) {
            accumulator[key] = [];
        }
        accumulator[key].push(currentValue);
        return accumulator;
    }, {});
}

let data = [
    { id: 1, type: 'fruit' },
    { id: 2, type: 'vegetable' },
    { id: 3, type: 'fruit' }
];

let groupedData = groupBy(data, item => item.type);
console.log(groupedData); // 输出: { fruit: [{ id: 1, type: 'fruit' }, { id: 3, type: 'fruit' }], vegetable: [{ id: 2, type: 'vegetable' }] }

通过这些实战案例,我们可以看到如何在实际应用中综合使用各种数组方法来解决复杂的问题。掌握这些技巧将极大地增强你在日常开发中的效率和代码质量。

我们继续深入探讨JavaScript数组的更多高级用法和实战案例。

高级数组操作

1. 数组的高级迭代

除了常见的迭代方法(如forEach, map, filter, reduce),还有一些其他的迭代方法可以帮助我们更方便地处理数组:

  • every(): 测试数组中的所有元素是否都通过了被提供的函数测试。
  • some(): 测试数组中是否有至少一个元素通过了被提供的函数测试。
let numbers = [1, 2, 3, 4, 5];

// 检查数组中的所有元素是否都大于0
let allPositive = numbers.every(num => num > 0);
console.log(allPositive); // 输出: true

// 检查数组中是否存在至少一个偶数
let containsEven = numbers.some(num => num % 2 === 0);
console.log(containsEven); // 输出: true
2. 数组的搜索
  • includes(): 判断数组中是否包含某个元素。
  • indexOf(): 返回数组中第一个匹配指定值的元素的索引,如果没有找到则返回-1。
  • lastIndexOf(): 类似于indexOf,但是返回的是最后一个匹配元素的索引。
let letters = ['a', 'b', 'c', 'd'];

// 检查数组中是否包含 'c'
let containsC = letters.includes('c');
console.log(containsC); // 输出: true

// 查找 'c' 的索引
let indexC = letters.indexOf('c');
console.log(indexC); // 输出: 2

// 查找最后一个 'c' 的索引
let lastIndexC = letters.lastIndexOf('c');
console.log(lastIndexC); // 输出: 2

实战案例:数组的综合运用

案例七:数组去重

给定一个数组,去除重复的元素,并保持原有的顺序。

function removeDuplicates(array) {
    let seen = new Set();
    return array.filter(item => {
        if (!seen.has(item)) {
            seen.add(item);
            return true;
        }
        return false;
    });
}

let items = [1, 2, 2, 3, 4, 4, 4, 5];
let uniqueItems = removeDuplicates(items);
console.log(uniqueItems); // 输出: [1, 2, 3, 4, 5]
案例八:数组交集

给定两个数组,找出它们之间的交集。

function findIntersection(arr1, arr2) {
    return arr1.filter(item => arr2.includes(item));
}

let arr1 = [1, 2, 3, 4, 5];
let arr2 = [4, 5, 6, 7, 8];
let intersection = findIntersection(arr1, arr2);
console.log(intersection); // 输出: [4, 5]
案例九:数组并集

给定两个数组,找出它们的并集,并去除重复元素。

function findUnion(arr1, arr2) {
    let combined = arr1.concat(arr2);
    let uniqueCombined = [...new Set(combined)];
    return uniqueCombined;
}

let union = findUnion(arr1, arr2);
console.log(union); // 输出: [1, 2, 3, 4, 5, 6, 7, 8]
案例十:数组差集

给定两个数组,找出第一个数组中不在第二个数组中的元素。

function findDifference(arr1, arr2) {
    return arr1.filter(item => !arr2.includes(item));
}

let difference = findDifference(arr1, arr2);
console.log(difference); // 输出: [1, 2, 3]

性能考量

在处理大量数据时,数组操作的性能尤为重要。以下是一些提高数组操作性能的建议:

  • 减少嵌套层次:尽量减少数组操作中的嵌套层次,以减少计算负担。
  • 使用适当的迭代方法:不同的迭代方法有不同的性能特点,比如mapfilter通常比forEach更快,因为它们返回新的数组。
  • 避免不必要的数组复制:使用像slice这样的方法会创建新的数组副本,这可能会消耗更多的内存和时间。尽可能使用原地操作(如sort)来避免不必要的复制。

总结

通过上述案例和技巧,我们可以看到JavaScript数组的强大功能和灵活性。掌握这些方法不仅可以帮助我们写出更简洁、高效的代码,还可以解决实际开发中遇到的各种复杂问题。在实践中不断尝试和优化,将使我们在处理数组数据时更加得心应手。

我们继续探讨JavaScript数组的一些进阶用法和应用场景。

高级数组操作与应用

1. 数组的扁平化与嵌套

有时我们需要处理嵌套的数组结构,例如将多层嵌套的数组扁平化为一层数组。

function deepFlatten(array) {
    return array.reduce((acc, val) => {
        return Array.isArray(val) ? acc.concat(deepFlatten(val)) : acc.concat(val);
    }, []);
}

let nestedArray = [1, [2, [3, 4], 5], 6];
let flatArray = deepFlatten(nestedArray);
console.log(flatArray); // 输出: [1, 2, 3, 4, 5, 6]
2. 数组的分页

处理大量数据时,可能需要将数组分成小段,以便分页显示。

function paginateArray(array, pageSize, pageNumber) {
    const startIndex = (pageNumber - 1) * pageSize;
    const endIndex = startIndex + pageSize;
    return array.slice(startIndex, endIndex);
}

let largeArray = Array.from({ length: 100 }, (_, i) => i + 1);
let paginatedArray = paginateArray(largeArray, 10, 2);
console.log(paginatedArray); // 输出: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
3. 数组的批处理

在处理大量数据时,可能需要将数据分批处理,例如每批处理一定数量的数据项。

function batchProcess(array, batchSize, processor) {
    let results = [];
    for (let i = 0; i < array.length; i += batchSize) {
        let batch = array.slice(i, i + batchSize);
        results.push(processor(batch));
    }
    return results;
}

function processBatch(batch) {
    return batch.map(item => item * 2);
}

let numbers = Array.from({ length: 20 }, (_, i) => i + 1);
let processedBatches = batchProcess(numbers, 5, processBatch);
console.log(processedBatches); // 输出: [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20], [22, 24, 26, 28, 30]]

多维数组处理

多维数组在处理表格数据、矩阵运算等方面非常有用。下面是一个处理多维数组的例子。

案例十一:矩阵转置

给定一个二维数组(矩阵),将其转置。

function transpose(matrix) {
    return matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));
}

let matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

let transposedMatrix = transpose(matrix);
console.log(transposedMatrix); // 输出: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
案例十二:矩阵乘法

实现两个矩阵的乘法运算。

function multiplyMatrices(m1, m2) {
    if (m1[0].length !== m2.length) {
        throw new Error('Matrix dimensions must agree.');
    }

    let result = [];

    for (let i = 0; i < m1.length; i++) {
        result[i] = [];
        for (let j = 0; j < m2[0].length; j++) {
            let sum = 0;
            for (let k = 0; k < m1[0].length; k++) {
                sum += m1[i][k] * m2[k][j];
            }
            result[i][j] = sum;
        }
    }
    return result;
}

let m1 = [
    [1, 2],
    [3, 4]
];

let m2 = [
    [5, 6],
    [7, 8]
];

let product = multiplyMatrices(m1, m2);
console.log(product); // 输出: [[19, 22], [43, 50]]

性能优化

在处理大量数据时,性能优化非常重要。以下是一些优化技巧:

1. 减少函数调用

在循环中尽量减少函数调用次数,因为每次调用函数都有一定的开销。

2. 使用尾递归优化

对于递归算法,如果语言支持尾递归优化,可以改写递归为尾递归形式以提高性能。

3. 使用缓存

对于重复计算的结果,可以使用缓存来避免多次计算。

4. 减少数组操作

尽量减少数组的创建和销毁,特别是对于大数组。

实战练习

为了巩固所学的知识,下面是一些实战练习题目:

  1. 数组旋转:给定一个数组和一个旋转步数,将数组向右旋转指定的步数。
  2. 数组的最大连续子数组和:给定一个数组,找到其中最大和的连续子数组,并返回其和。
  3. 数组的K个最近邻居:给定一个数组和一个目标值,找出数组中最接近目标值的K个数。

通过这些实战练习,你可以更好地掌握JavaScript数组的各种操作,并能够灵活运用到实际开发中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2206588.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于差分进化灰狼混合优化的SVM(DE-GWO-SVM)数据预测算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 DE优化 4.2 GWO优化 5.完整程序 1.程序功能描述 基于差分进化灰狼混合优化的SVM(DE-GWO-SVM)数据预测算法matlab仿真&#xff0c;对比SVM和GWO-SVM。 2.测试软件版本以及运行结果展示…

VMwareWorkstation安装KylinV10sp3(银河麒麟)系统教程

版本说明 VMware版本如下 OS版本如下 创建虚拟机 点击创建新的虚拟机 按图下所示选择&#xff0c;点击下一步 按照图下所示选择&#xff0c;点击下一步 按照图下所示选择&#xff0c;点击下一步 按照图下所示选择&#xff0c;点击下一步 设置虚拟机名称&#xff0c;点击下一步…

【RabbitMQ高级——过期时间TTL+死信队列】

1. 过期时间TTL概述 过期时间TTL表示可以对消息设置预期的时间&#xff0c;在这个时间内都可以被消费者接收获取&#xff1b;过了之后消息将自动被删除。RabbitMQ可以对消息和队列设置TTL。 目前有两种方法可以设置。 第一种方法是通过队列属性设置&#xff0c;队列中所有消…

Ubuntu安装Apache教程

系统版本&#xff1a;Ubuntu版本 23.04 Ubuntu是一款功能强大且用户友好的操作系统&#xff0c;而Apache是一款广泛使用的Web服务器软件。在Ubuntu上安装Apache可以帮助用户搭建自己的网站或者进行Web开发。为大家介绍如何在Ubuntu上安装Apache&#xff0c;并提供详细的教程和操…

青云AI算力创新:直击AI落地痛点 打造企业数智化基石

在当今这个数字化、智能化的时代&#xff0c;企业数字化转型、智能化升级应用实践在加速&#xff0c;AI算力已经成为企业数字化转型和智能化升级的重要基石&#xff0c;而AI算力在推动技术创新和业务增长中起到了关键作用。青云科技近日举办的AI算力发布会&#xff0c;标志着AI…

Numpy模块中的ndarray对象属性、数组的重塑、合并、分割

一、ndarray对象属性介绍 说明&#xff1a;ndim属性返回数组的维度&#xff0c;即数组有多少个轴。例如&#xff0c;一维数组的ndim为1&#xff0c;二维数组的ndim为2&#xff0c;以此类推。 示例1&#xff1a; # coding:utf-8 import numpy as np wnp.array([[1,2,3],[4,5,6…

Java如何保证线程T1,T2,T3 顺序执行?

文章目录 方案 1&#xff1a;使用 Thread.join()方案 2&#xff1a;使用 Lock 和 Condition方案 3&#xff1a;使用 CyclicBarrier方案 4&#xff1a;使用 Semaphore总结 博主介绍&#xff1a;全网粉丝10w、CSDN合伙人、华为云特邀云享专家&#xff0c;阿里云专家博主、星级博主…

初始操作系统篇(1)—— 操作系统的概念与分类

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 操作系统 目录 操作系统的基本概念 操作系统的概念 操作系统的特征 并发 共享 虚拟 异步 操作系统的目标和功能 操作系统的发展与分…

T11:优化器对比实验

T11周&#xff1a;优化器对比实验 **一、前期工作**1.设置GPU,导入库 **二、数据预处理**1.导入数据2.检查数据3.配置数据集4.数据可视化 **三、构建模型****四、训练模型****五、模型评估**六、总结 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&a…

QT实现Opencv图像处理

案例 基于QT的人脸识别 pro文件需要加以下代码 INCLUDEPATH E:/opencv/opencv3.4-qt-intall/install/include INCLUDEPATH E:/opencv/opencv3.4-qt-intall/install/include/opencv INCLUDEPATH E:/opencv/opencv3.4-qt-intall/install/include/opencv2 LIBS E:/opencv/o…

Linux go语言配置

首先安装go语言 先从go官方下载源码 解压&#xff1a; tar -xzvf go1.23.1.linux-amd64.tar.gz 移动go到 /usr/local/ mv go /usr/local 设置环境变量 vi ~/.bashrc source ~/.bashrc 重新获取文件 输入 go version 查看版本

STM32 A/D转换器

目录 模拟量输入通道 A/D转换器简介 模拟量输入信号类型与量程自动转换 量程自动转换 STM32F103ZET6集成的ADC模块 STM32的ADC的主要特征 STM32的ADC模块结构 ADC中断事件主要有以下3个&#xff1a; 模拟量输入通道 模拟量输入通道一般由信号处理、模拟开关、放大器、采…

MES管理系统解决方案常见的应用场景

在现代制造业的浪潮中&#xff0c;车间管理的效率与智能化水平成为了企业竞争力的关键因素。许多车间管理者都耳闻MES管理系统解决方案能够显著优化生产执行流程&#xff0c;但由于缺乏亲身体验&#xff0c;往往对此持保留态度。那么&#xff0c;MES管理系统究竟能否如传闻般发…

po框架的了解和应用

https://www.cnblogs.com/xiaolehong/p/18458470 笔记 任务:1、通过po框架输入测试报告 2、编写自动化测试框架 3、总结测试讲解稿 自动化测试框架概念: 自动化测试框架是一个集成体系,这个体系中包含测试功能的函数、测试数据源、测试对以及重要的模块。 作用:用于解决或…

MIDIPLUS 50周年丨中国国际乐器展览会首日盛况

10月10日&#xff0c;由中国乐器协会、上海国展展览中心有限公司、法兰克福展览&#xff08;上海&#xff09;有限公司共同主办的中国&#xff08;上海&#xff09;国际乐器展览会在上海新国际博览中心&#xff08;上海市浦东新区龙阳路2345号&#xff09;盛大开幕。 2024上海…

ART 光学跟踪系统:通过 VR HMD 解锁完全沉浸式 VR 体验

在虚拟现实体验中&#xff0c;完全沉浸式虚拟现实体验应该既准确又舒适。当与现实世界的物体融合时&#xff0c;虚拟现实的表现必须与现实精确匹配。这意味着所使用的运动跟踪系统必须为整套项目提供可靠且可重复的高精度运动数据&#xff0c;以及体感无法察觉到的超低延迟。AR…

水深探测仪的作用和使用方法

在水域救援的行动里&#xff0c;救援人员时刻面临着复杂多变、充满未知的水域状况。当接到救援任务奔赴现场&#xff0c;那片需要涉足的水域就像一个神秘莫测的异世界&#xff0c;挑战着所有人的认知与勇气。 水深探测仪作为一种专用于测量水域深度的设备&#xff0c;通过声波和…

宝塔 进程守护管理器 神坑,再次跌入。thinkphp-queue队列 勤勤学长

如果&#xff0c;你有在使用【进程守护管理器】&#xff0c;记得在更新/重启&#xff0c;甚至卸载重新安装后&#xff0c;重启服务器。 事情的起因是&#xff0c;昨日服务器突然异常&#xff0c;网站无法正常访问&#xff0c;进入宝塔面板&#xff0c;发现 cpu和负载率均超过1…

甘肃小米,一口软糯,满是乡愁

&#x1f388;甘肃小米&#xff0c;自然的馈赠&#x1f388;&#x1f33e;家人们&#xff0c;今天必须给大家安利来自甘肃的小米&#xff01;&#x1f49b;✨甘肃&#xff0c;那片广袤而神奇的土地&#xff0c;孕育出的小米有着别样的魅力。颗粒饱满&#xff0c;色泽金黄&#…

RDD优化:缓存和checkpoint机制、数据共享(广播变量、累加器)、RDD的依赖关系、shuffle过程、并行度说明

文章目录 1. 缓存和checkpoint机制1.1 缓存使用1.2 checkpoint1.3 缓存和checkpoint的区别 2. 数据共享2.1 广播变量2.2 累加器 3. RDD依赖关系4.shuffle过程4.1 shuffle介绍4.2 spark计算要尽量避免shuffle 5. 并行度 1. 缓存和checkpoint机制 缓存和checkpoint也叫作rdd的持…