数组是属于线性结构的一种,是顺序存储的结构
数组是一个有序的元素序列,用于存储多个相同类型的集合
但在JS中,一个数组中的元素并不强调是同一个类型,可以包含多个数据类型的元素

数组的属性
数组里的各个变量称为数组的元素
用于区分各个元素的数字编号被称为下标
容纳元素的总数称为数组的长度

常见的数据操作

  1. // 1. 增加
  2. // 前增, unshift, 返回值为添加后的数组长度,会改变原数组
  3. let arr = [1] // [1]
  4. arr.unshift(2) // [2, 1]
  5. // push 后增,返回添加后的新数组长度,会改变原数组
  6. arr.push(3) // [2,1,3]
  7. // 2. 删除
  8. // shift 前删, 返回删除的元素,会改变原数组
  9. let arr1 = [1,2,3]
  10. arr.shift() // 1
  11. console.log(arr1) // [2,3]
  12. // pop, 后删, 返回删除的元素,会改变原数组
  13. arr1.pop() // 3;
  14. console.log(arr1) // [2]
  15. // 3. 替换, 返回删除元素组成的新数组,会改变原数组
  16. let arr2 = [1,2,3,4]
  17. arr2.splice(0, 1) // [1], 表示从0开始删除一个元素
  18. console.log(arr2) // [2,3,4]
  19. arr2.splice(1,2,9) // [3,4] // 从索引1开始删除2个元素并替换成9
  20. console.log(arr) // [2, 9]
  21. arr2.splice(3, 0, 10) // [], 从索引3开始,不删除元素,并添加元素10
  22. console.log(arr2) // [2, 9, 10]
  23. // 4. 拼接
  24. // push, 返回添加的后数组长度,会改变原数组
  25. let a1 = [1,2]
  26. let a2 = [3,4]
  27. a1.push(a2)
  28. console.log(a1) // [1,2,[3,4]]
  29. // concat,返回拼接后的副本,不会改变原数组
  30. let a3 = [1,2]
  31. let a4 = [3,4]
  32. let a5 = a3.concat(a4)
  33. console.log(a5) // [1,2,3,4]
  34. // 5. 查找
  35. // 1. indexOf, 返回数组中首次出现的下标,如果找不到,返回-1, 不改变原数组
  36. let a6 = [1,2,3,1,5]
  37. let index = arr.indexOf(1);
  38. console.log(index); // 0
  39. // 2. lastIndexOf
  40. let a7 = [1,2,1,2,1,2]
  41. let index = arr.indexOf(1);
  42. console.log(index); // 4
  43. // 6. 排序
  44. // sort, 按照默认排序进行排序,返回排序好的数组,会改变原数组
  45. let a8 = [5,7,3,9,1,6]
  46. arr.sort() // [1,3,5,6,7]
  47. // reverse, 将数组逆序排列,会改变原数组
  48. arr.reverse() // [7,6,5,3,1]
  49. // 7. 转换
  50. // toString, 转换为字符串, 不会改变原数组
  51. let a9 = [1, 2]
  52. let str = a9.toString()
  53. console.log(str) // '1,2'
  54. // join, 使用特定分隔符将数组中的元素连接起来,并以字符串的形式输出,不会改变原数组
  55. let a10 = [1,2,3]
  56. let str1 = a10.join('.')
  57. console.log(str1) // '1.2.3'
  58. let str2 = a10.join('$')
  59. console.log(str2) // '1$2$3'

数组的优劣
优点:更新查找块,使用下标访问, O(1)的时间复杂度
缺点: 增删慢,O(n)的时间复杂度

数组乱序的实现
方法一:

  1. 得到数组最后一个元素的下标,然后开始逆序数组
  2. 获得从0到当前元素的随机元素,并让两个元素交换位置
  3. 交换两个元素,需要创建中间变量保存当前元素
  4. 由于数组是引用类型,改变传入参数arr的同时,也会修改原数组 ```javascript function shuffle(arr) { for (let i= arr.length - 1; i >= 0; i—) { let rIndex = Math.floor(Math.random() * (i + 1)); let temp = arr[rIndex] arr[rIndex] = arr[i] arr[i]= temp }

    return arr } let arr = [1,2,3]

  1. 一种更简单的方法使用sort实现
  2. 1. 不传参数时,sort会使用默认排序方式,先调用每个元素的toString()防范,然后按照转换后的字符串的Unicode编码来进行排序
  3. 1. 传入函数参数,参数只能是函数,可以开发者按照自己的意愿对元素进行排序
  4. 1. 如果传入的函数参数,返回的结果是随机的,会出现数组乱序的现象
  5. ```javascript
  6. function shuffle(arr) {
  7. return arr.sort((a, b)=> Math.random() > .5 ? -1: 1)
  8. }

小结

  1. 数组的逻辑结构 - 顺序存储
  2. 数组的基本操作方法,增, 删,改,查,拼,排,转
  3. 通过sort实现数组乱序

练习题

如何在一个成对的数组中找出某个缺失的元素

  1. let arr = [1,1,2,2,3]
  2. function searchOnly(arr) {
  3. // todo...
  4. }
  5. console.log(searchOnly(arr)); // 输出3

运算符知识点, ^ 操作二进制数据, 逐位比较,相等为0 不等为1
例如: 2 的 二进制位 10, 3 的 二进制位11, 2^3 = 01 => 1
任何数异或0 - 不变
任何数异或自身 - 0
reduce聚合方法,接受一个函数为参数

  1. let b = [1,2,3,4]
  2. b.reduce((prev, next) => prev + next) // 结果为10
  3. // prev 为上一次操作的结果
  4. // next 为下一个参数
  5. // 执行顺序
  6. // 1 + 2 = 3
  7. // 3 + 3 = 6
  8. // 6 + 4 = 10

实现searchOnly

  1. let arr = [1,1,2,2,3]
  2. function searchOnly(arr) {
  3. return arr.reduce((prev, next) => prev ^= next)
  4. }
  5. console.log(searchOnly(arr)); // 输出3