首页 > 其他分享 >数据结构-数组

数据结构-数组

时间:2024-03-26 19:35:11浏览次数:21  
标签:arr 81 console log avgTempArr 数组 数据结构

数组是一种最为常见和应用广泛的数据结构, 不用语言的数组不太一样, 对于 js 的数组来说, 和 python 的列表极其类似, 都是可动态拓展值和类型的, 还是来大致总结一下这个基础数据结构.

创建数组

let arr1 = new Array('a', 'b', 66)
let arr2 = ['a', 'b', 66]

console.log(arr1, arr2);

数组访问和迭代

  • 递归
  • for 索引
  • for / of 值
const fibArr = []
fibArr[1] = 1
fibArr[2] = 1

for (let i = 3; i < 20; i++) {
  fibArr[i] = fibArr[i-1] + fibArr[i-2]
}

for (let i = 1; i < fibArr.length; i++) {
  console.log(fibArr[i]);
}

console.log(fibArr);

更多场景是我们直接遍历数组元素, 类似的结构是: arr = [ {}, {}, {} ...] 推荐用 for ... of

const arr = [1, 2, 3, {'name': 'cj', age: 18}]

for (let item of arr) {
  console.log(item);
}
PS F:\algorithms> node .\array.js
1
2
3
{ name: 'cj', age: 18 }

添加元素

  • push
  • unshift
  • Array.prototype. xxx = function (value) =>
let arr = []

// 尾插
arr.push(666)
arr[arr.length] = 888

console.log(arr);

// 头插
Array.prototype.insertHead = function(value) {
  for (let i = this.length; i >= 0; i--) {
    this[i] = this[i-1]
  }
  this[0] = value 
}

arr.unshift(2, 3)

arr.insertHead(111)
console.log(arr);
PS F:\algorithms> node .\array.js
[ 666, 888 ]
[ 2, 3, 111, 666, 888 ]

删除元素

  • pop
  • shift
  • Array.prototype.xxx = function(value) =>
let arr = [1, 2, 3, 4, 'cj', 'nb']

// 尾删
item = arr.pop()
// 头删
item2 = arr.shift()

console.log(item, item2, arr);
nb 1 [ 2, 3, 4, 'cj' ]

当然从头部删除也可以通过如下两个步骤:

  • 创建一个 reIndex 的方法, 接收一个数组, 然后过滤掉 undefined 的元素, 返回新数组
  • 通过索引方式手动删除原数组第一个元素, 然后将这个结果丢到 reIndex 中即可
// 将数组中的中 undefined 元素过滤
Array.prototype.reIndex = function (arr) {
  const newArr = []
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] != undefined) newArr.push(arr[i])
  }
  return newArr
}

// 手动删除第一个元素并排序
Array.prototype.removeHead = function() {
  for (let i = 0; i < this.length; i++) {
    this[i] = this[i+1]
  }
  return this.reIndex(this)
}


let arr = [1, 2, 3, 4, 'cj', 'nb']
console.log(arr.removeHead());

[ 2, 3, 4, 'cj', 'nb' ]

在任意位置添加或者删除元素

  • splice (start, deleteCount, item1, item2, ...))
  • 可增, 可删, 可替换

两个值的时候, 就是删除

arr = [1, 2, 3, 4, 5, 6]

// 从索引 2 的位置, 删除 2个元素
arr.splice(2, 2)

console.log(arr)
[ 1, 2, 5, 6 ]

多个值的时候, 可以是新增, 比如在索引为 2 的位置, 往前新增两个元素, 10, 11

arr = [1, 2, 3, 4, 5, 6]

// 索引为 2 的位置, 往前新增两个元素, 10, 11
arr.splice(2, 0, 10, 11)

console.log(arr)
[ 1, 2, 10, 11, 3, 4,  5,  6 ]

同样, 如果是要将索引为 2 的位置删掉, 再替换也是一样的, deleteCount 设置为 1 即可.

arr.splice(2, 1)         // 表示删掉索引为 2 的元素
arr.splice(2, 1, 10, 11) // 表示删掉索引为 2 的元素, 并原地插入 10, 11

多维数组

类似, 矩阵, 多层级的 json 等都基本可以通过一维数组方式实现, 在实际应用中用得最多的就是二维数组. 这里我们以矩阵来做一个演示.

以两天监测的平均华氏气温为例:

let avgTempDay01 = [ 72, 75, 79, 79, 81, 81]
let avgTempDay02 = [ 81, 79, 75, 75, 73, 72]

显然这样来存储是比较分散的, 通过矩阵或者二维数组的方式则更好一些.

let avgTempArr = []
// day01
avgTempArr[0] = []
avgTempArr[0][0] = 72
avgTempArr[0][1] = 75
avgTempArr[0][2] = 79
avgTempArr[0][3] = 79
avgTempArr[0][4] = 81
avgTempArr[0][5] = 81

// day02
avgTempArr[1] = []
avgTempArr[1][0] = 81
avgTempArr[1][1] = 79
avgTempArr[1][2] = 75
avgTempArr[1][3] = 75
avgTempArr[1][4] = 73
avgTempArr[1][5] = 72

console.log(avgTempArr);
PS F:\algorithms> node .\array.js
[ [ 72, 75, 79, 79, 81, 81 ], [ 81, 79, 75, 75, 73, 72 ] ]

当然也可以简写成这样:


let avgTempArr = []

avgTempArr[0] = [ 72, 75, 79, 79, 81, 81]
avgTempArr[1] = [ 81, 79, 75, 75, 73, 72]

二维数组迭代

  • 嵌套 for 循环即可, 先行后列的方式
function printMatrix(matrix) {
  for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < matrix[i].length; j++) {
      console.log('pos:', [i, j], matrix[i][j])
    }
  }
}


let avgTempArr = []
avgTempArr[0] = [ 72, 75, 79, 79, 81, 81]
avgTempArr[1] = [ 81, 79, 75, 75, 73, 72]

console.log(avgTempArr);
printMatrix(avgTempArr)
PS F:\algorithms> node .\array.js
[ [ 72, 75, 79, 79, 81, 81 ], [ 81, 79, 75, 75, 73, 72 ] ]

pos: [ 0, 0 ] 72
pos: [ 0, 1 ] 75
pos: [ 0, 2 ] 79
pos: [ 0, 3 ] 79
pos: [ 0, 4 ] 81
pos: [ 0, 5 ] 81
pos: [ 1, 0 ] 81
pos: [ 1, 1 ] 79
pos: [ 1, 2 ] 75
pos: [ 1, 3 ] 75
pos: [ 1, 4 ] 73
pos: [ 1, 5 ] 72

数组常用方法

在JavaScript里,数组是经过改进的对象,这意味着创建的每个数组都有一些可用的方法。数组很有趣,因为它十分强大,和 Python 里面的列表类似的. 且相比其他语言中的数组,JavaScript中的数组有许多很好用的方法.

常用数组方法 描述 示例
push / pop 在尾部添加, 删除元素 arr.push(1, 2); item = arr.pop()
unshift / shift 在头部添加, 删除元素 arr.unshift(); arr.shift()
concat 拼接2个或多个数组, 并返回截个屏 arr1.concat(arr2, arr3)
join 将数组元素拼接为一个字符串 arr.join( ) 通常配合字符的 split 用
indexOf 查找元素第一次出现的索引, 没有则 -1 arr.indexOf('item')
slice 查找索引范围内的元素, 前闭后开 arr.slice(1, 3) 返回索引为 1, 2 的元素
reverse 将数组元素反序, 原地修改 arr.reverse()
sort 不传参按字母排序, 传参(函数) 按函数排 arr.sort((a, b) => b - a) 降序
map 传回调函数处理每个元素, 返回新数组 arr2 = arr.map((item) => item * 2) 每个元素平方
filter 传回调呼声判断每个元素结果为 true 的, 返回新数组 arr2 = arr.filter((item) => item % 2 == 0) 只要偶数
forEach 传回调函数, 遍历数组处理, 无返回值 arr.forEach((item, index) => console.log(item, index))
every / some 传回调函数, 判断每个元素, 存在 / 所有 返回 Boolean arr.some((item) => item % 2 == 0 )
includes 判断是否存在某个元素, 返回 Boolean arr.includes('item') 感觉和 indexOf 也差不多
from / ... 对数组的浅拷贝 arr2 = arr.from(arr) ; arr2 = [...arr]

数组/对象的深拷贝

数组是引用类型, 在更多应用中会将一些数据包装成数组或对象形式传给后端接口, 通常就浅拷贝就行, 如果不会在多个应用中共用的话:

  • arr2 = [ ...arr ]
  • arr2 = Array.from(arr)
  • arr2 = arr.slice()
  • arr2 = arr.map(item => item)

就浅拷贝不胜枚举. 但我们更多的是关注深拷贝.

第一种深拷贝的简单粗暴方法是用 JSON.parse(JSON.stringify( ) ) 即先将数组序列化字符串, 再进行反序列化成数组.

const arr = [1, 2, 3, {'name': 'cj', age: 18}]

const arr2 = JSON.parse(JSON.stringify(arr))

arr[3].name = 'ccc'
console.log('arr: ', arr)
console.log('arr2: ', arr2)
PS F:\algorithms> node .\array.js
arr:  [ 1, 2, 3, { name: 'ccc', age: 18 } ]
arr2:  [ 1, 2, 3, { name: 'cj', age: 18 } ]

第二种方法是通过 递归 的方式层层遍历数组元素:

  • 先定义一个空数组, 或者空对象
  • 遍历数组元素, 判断当类型为 Array 时候, 再继续递归遍历
  • 判断当类型为 Object 时候, 再继续递归遍历
  • 当为普通元素时, 添加进数组 (递归终止条件)
function deepClone(obj) {
  // 先要判断 obj 是数组, 对象, 还是基本类型
  // 优先数组处理, 因为数组也是对象

  if (Array.isArray(obj)) {
    // 数组
    var ret = []
    for (var item of obj) {
      ret.push(deepClone(item))
    }
  } else if (typeof obj == 'object') {
    // 对象
    var ret = {}
    for (var key in obj) {
      ret[key] = deepClone(obj[key])
    }
  } else {
    // 基本类型直接输出, 作为递归出口
    var ret = obj
  }
  return ret 
}


const arr = [1, [{'a': 55}, 9], 3, {'name': 'cj', age: 18}]

const arr2 = deepClone(arr)

arr[3].name = 'ccc'
console.log('arr: ', arr)
console.log('arr2: ', arr2)

PS F:\algorithms> node .\array.js
arr:  [ 1, [ { a: 55 }, 9 ], 3, { name: 'ccc', age: 18 } ]
arr2:  [ 1, [ { a: 55 }, 9 ], 3, { name: 'cj', age: 18 } ]

数组排序

先是反序的 reverse 原地方法.

const arr = [1, 2, 3, 'cj']
arr.reverse()
console.log(arr);
PS F:\algorithms> node .\array.js
[ 'cj', 3, 2, 1 ]

然后是数组排序的 sort 方法. 当不传函数时候, 就默认以字符排序, 注意不是数值哦, 一定要记得穿一个比较函数进去!!!

const arr = [1, 2, 80, 9]
arr.sort()
console.log(arr);
PS F:\algorithms> node .\array.js
[ 1, 2, 80, 9 ]

默认是字符排序, 所以进行升序或者降序的时候, 必须要传入一个compareFn .

const arr = [1, 2, 3, 1, 0, 'cj']
// a -b 升序默认, b-a 降序
arr.sort((a, b) => b -a )

console.log(arr);
PS F:\algorithms> node .\array.js
[ 3, 2, 1, 1, 0, 'cj' ]

至此, 关于 javascript 的数组结构就差不多到这了.

标签:arr,81,console,log,avgTempArr,数组,数据结构
From: https://www.cnblogs.com/chenjieyouge/p/18097388

相关文章

  • 十八 1265. 数星星 (树状数组)
    1265.数星星(树状数组)思路:本题要统计每个星星左下角星星的数目,由于星星按y坐标增序给出,y坐标相同的按x坐标增序给出,所以不用关注y,可以视作每个x位置有几颗星星就为几的数组,每次统计左侧前缀和,再将当前计算的星星x位置数加一,使用树状数组(推荐视频:五分钟丝滑动画讲解|树状数......
  • 王道数据结构2025顺序表课后题5,6
    5.有序顺序表中删除所有值重复的元素,使元素值均不同。思路:利用一个新的顺序表存储元素,遍历重复元素的顺序表只要当前元素与新顺序表元素不同则进入。//5.从有序顺序表中删掉所有重复的元素sqlist1quchong(sqlist1L1)//122448{ if(L1.length1!=0) { sqli......
  • 【图论 | 数据结构】用链式前向星存图(保姆级教程,详细图解+完整代码)
    一、概述链式前向星是一种用于存储图的数据结构,特别适合于存储稀疏图,它可以有效地存储图的边和节点信息,以及边的权重。它的主要思想是将每个节点的所有出边存储在一起,通过数组的方式连接(类似静态数组实现链表)。这种方法的优点是存储空间小,查询速度快,尤其适合于处理大规模......
  • 代码随想录算法训练营day34 | leetcode 1005. K 次取反后最大化的数组和、134. 加油站
    目录题目链接:1005.K次取反后最大化的数组和-简单题目链接:134.加油站-中等题目链接:135.分发糖果-困难题目链接:1005.K次取反后最大化的数组和-简单题目描述:给你一个整数数组nums和一个整数k,按以下方法修改该数组:选择某个下标i并将nums[i]替换为-nums[i]。重......
  • LeetCodeHot100 数组 53. 最大子数组和 56. 合并区间 238. 除自身以外数组的乘积
    53.最大子数组和https://leetcode.cn/problems/maximum-subarray/description/?envType=study-plan-v2&envId=top-100-likedpublicintmaxSubArray(int[]nums){int[]dp=newint[nums.length];dp[0]=nums[0];for(inti=1;i<nums......
  • 第三篇-Javascript数组
    什么是数组数组指一组有序数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。可以通过new关键字来创建数组。Javascript访问数组1、通过索引访问单个元素:letarr=[1,2,3,4,5];console.log(arr[0]);//输出1console.log(arr[2]);//输出3cons......
  • C语言数组
    概念一组相同类型元素的集合定义intarr【10】={1,2,3,4,5,6,7,8,9};//定义一个整型数组,最多放10个元素。数组的下标数组的每个元素都有一个下标,下标从0开始,且数组通过下标来访问。如下面程序intmain(){    intarr【10】={10,11,12,13,14,15,16,17,18,19};    printf......
  • Java-数组
    在Java中,数组是一种基本的数据结构,用于存储固定大小的同类型元素集合。以下是Java中数组的相关知识:数组的声明数组声明包括指定数组的类型和数组的名称。数组类型可以是任何基本数据类型或对象类型。int[]numbers;//声明一个整型数组String[]names;//声明一个字符......
  • 【数据结构】C语言单链表的实现
    有时我们不用顺序表,而使用链表,是因为顺序表存在一定的问题1、顺序表的中间/头部的插入、删除需要挪动数据2、扩容需要申请新空间,拷贝数据,释放旧空间,存在性能的消耗3、会有空间的浪费单链表:不带头单向循环链表双链表:带头双向循环链表单链表的具体实现:1、单链表的创建:2......
  • 写模板,树状数组。
    1根据长度初始化,单点更新,区间查询。可以查询区间和(输入为位置+数值),可以查询区间内频次(输入为数值+频次1)。2根据输入数据线性初始化。3根据输入数据频次线性初始化,区间更新,单点查询。根据差分后的数组求前缀和(单点查询)。classFenwickTree{public:FenwickTree(......