数组
数组简介和基本使用
简介
数组(Array),顾名思义,用来存储组相关的值,从而方便进行求和、计算平均数、逐项遍历等操作。
定义方法
- var arr=[1,2,3]
- var arr=new Array(1,2,3) //包装类
- var arr=new Array(3) // 长度为 3 的数字,每一项都是 undefined
访问数组项
数组每一项都有下标,下标从 0 开始
var arr = (1, 2, 3)
arr[1] // 2
下标越界
JavaScrip 规定,访问数组中不存在的项会返回 undefined,不会报错
数组的长度
- 数组的 length 属性表示它的长度
- 数组最后一项的下标是数组的长度减 1
更改数组项
- 数组并不是只读的,我们可以修改它其中任何项的值
- 如果更改的数组项超过了 length-1,则会创造这项
数组的遍历
var arr = [1, 2, 3]
for (var i = 0; i < arr.length; i++) {
console.log(arr[i])
}
数组类型的检测
- arr instanceof Array // 返回 true
- arr.isArray()方法
数组的常用方法
数组的头尾操作
- push()
- push()方法用来在数组末尾推入新项,参数就是要推入的项
- 如果要推入多项,可以用逗号隔开
- 调用 push()方法后,数组会立即改变,不需要赋值
- 该方法会返回新的长度
- pop()
- 与 push()相反,pop()方法用来删除数组中的最后一项
- pop()方法不仅会删除数组末项,而且会返回被删除的项
- unshift()
- unshift()方法用来在数组头部插入新项,参数就是要插入的项
- 如果要插入多项,可以用逗号隔开
- 调用 unshift()方法后,数组会立即改变,不需要赋值
- 该方法会返回新的长度
- shift()
- 与 unshift()相反, shift()方法用来删除数组中下标为 0的项
- shift()方法不仅会删除数组首项,而且会返回被删除的项
splice()
- splice()方法用于替换数组中的指定项
var arr = [3, 1, 3, 4]
arr.splice(1, 2, 4, 5) //从下标为1的项开始,连续替换两项
console.log(arr) // [3,4,5,4]
- splice()方法可以用于在指定位置插入新项
var arr = [3, 1, 3, 4]
arr.splice(1, 0, 6, 7) // 在下标为1的位置插入两项,不替换
console.log(arr) // [3,6,7,1,3,4]
- splice()方法可以用于删除指定项
var arr = [3, 1, 3, 4]
arr.splice(1, 1) // 没有设置替换的新项,仅删除1项
console.log(arr) // [3,3,4]
- splice()方法会以数组形式返回被删除的项
slice()
- slice()方法返回一个新的数组对象,这一对象是一个由
begin
和end
决定的原数组的浅拷贝 - slice(a,b)截取的子数组从下标为 a 的项开始,到下标为 b(但不包括下标为 b 的项)结束
- slice(a,b)方法不会更改原有数组
- slice()如果不提供第二个参数,则表示从指定项开始,提取所有后续所有项作为子数组
- slice()方法的参数允许为负数,表示数组的倒数第几项
- 如果同时省略
begin
和end
参数,将返回一个原数组的浅拷贝
// 浅拷贝
let arr = [
1,
3,
{
username: ' kobe',
},
]
let arr3 = arr.slice()
arr3[2].username = 'wade'
console.log(arr) // [ 1, 3, { username: 'wade' } ]
join()和 split()
数组的 join()方法可以使数组转为字符串;字符串的split()方法可以使字符串转为数组。
- join()的参数表示以什么字符作为连接符,如果留空则默认以逗号分隔,如同调用 tostring()方法
- split()的参数表示以什么字符拆分字符串,一般不能留空=>(str.split(''))
'abcd'.split('') // [ 'a', 'b', 'c', 'd' ]
字符串和数组更多相关性
- 字符串也可以使用方括号内写下标的形式,访问某个字符等价于 charAt()方法,意味着字符串可以直接遍历
var str = '123456'
for (var i = 0; i < str.length; i++) {
console.log(str[i])
}
- 字符串的一些算法问题有时候会转换为数组解决
concat()
concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组
参数:数组和/或值,将被合并到一个新的数组中。如果没有参数,则 concat 会返回调用此方法的现存数组的一个浅拷贝
返回值:一个新的数组
const array1 = ['a', 'b', 'c']
const array2 = ['d', 'e', 'f']
const array3 = array1.concat(array2)
console.log(array3)
reverse()
reverse()方法用来将一个数组中的全部项顺序置反
indexOf()和 includes()
- indexOf()方法的功能是搜索数组中的元素,并返回它所在的位置,如果元素不存在,则返回-1
- includes()方法的功能是判断一个数组是否包含一个指定的值,返回布尔值
find()
find()
方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
callback
参数:当前遍历到的元素,当前遍历到的索引,数组本身
const array1 = [5, 12, 8, 130, 44]
const found = array1.find(element => element > 10)
console.log(found)
// expected output: 12
filter()
filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
返回值:一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。
callback(用来测试数组的每个元素的函数。返回 true 表示该元素通过测试,保留该元素,false 则不保留。)被调用时传入三个参数:元素的值,元素的索引,被遍历的数组本身
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']
const result = words.filter(word => word.length > 6)
console.log(result)
// expected output: Array ["exuberant", "destruction", "present"]
forEach()
forEach() 方法对数组的每个元素执行一次给定的函数
返回值:undefined
callback 被调用时传入三个参数:数组当前项的值,数组当前项的索引,数组对象本身
const array1 = ['a', 'b', 'c']
array1.forEach(element => console.log(element))
// expected output: "a"
// expected output: "b"
// expected output: "c"
var words = ['one', 'two', 'three', 'four']
words.forEach(function (word) {
console.log(word)
if (word === 'two') {
words.shift()
}
})
// one
// two
// four
map()
map()
方法的回调函数每次执行后的返回值组合起来形成一个新数组
返回值
:一个由原数组每个元素执行回调函数的结果组成的新数组。
callback
被调用时传入三个参数:数组元素
,元素索引
,原数组本身
;callback
每次执行后的返回值(包括 undefined
)组合起来形成一个新数组。
const array1 = [1, 4, 9, 16]
// pass a function to map
const map1 = array1.map(x => {
return x * 2
})
console.log(map1)
// expected output: Array [2, 8, 18, 32]
::: tip forEach() 和 map() 的区别
返回值:forEach()方法返回 undefined ,而 map()返回一个包含已转换元素的新数组
链接其他方法:map()方法输出可以与其他方法(如 reduce()、sort()、filter())链接在一起,以便在一条语句中执行多个操作。另一方面,forEach()不能与其他方法链接,因为它返回 undefined。
性能:map()方法比 forEach()转换元素要好。
中断遍历:这两种方法都不能用 break 中断,否则会引发异常
建议使用 map()转换数组的元素,因为它语法短,可链接且性能更好。
如果不想返回的数组或不转换数组的元素,则使用 forEach() 方法。
最后,如果要基于某种条件停止或中断数组的遍历,则应使用简单的 for 循环或 for-of / for-in 循环。
参考:数组中 forEach() 和 map() 的区别 :::
reduce()
reduce() 方法对数组中的每个元素执行一个由您提供的 reducer
函数,将其结果汇总为单个返回值。
返回值:函数累计处理的结果
参数:reducer
函数,initialValue
reducer 函数接收 4 个参数:
previousValue
(pre) (上一次调用 reducer 函数的返回值)currentValue
(cur) (数组中正在处理的元素)currentIndex
(idx) (数组中正在处理的元素的索引 )array
(arr) (用于遍历的数组)
每一次运行 reducer
函数会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
initialValue
(可选): 作为第一次调用 reducer
函数时的previousValue
的值。如果没有提供初始值,则将使用数组中的第一个元素,currentValue
将使用数组第二个元素;若指定了初始值 initialValue
,则 currentValue
则将使用数组第一个元素
const array1 = [1, 2, 3, 4]
total = array1.reduce((acc, cur) => {
return acc + cur
})
console.log(total) //10
sort()
特别注意
:sort 方法的返回值是对原数组的引用
。数组在原数组上进行排序,不生成副本。
const arr = [1, 2, 0, 123, -1]
const arr2 = arr.sort((a, b) => {
return a - b
})
console.log(arr) // [ -1, 0, 1, 2, 123 ]
console.log(arr === arr2) // true
- 升序排序
arrObject.sort(function(a,b){return a-b})
当 a==b 时,返回值是 0,a 和 b 不用交换位置。
当 a>b 时,返回值大于 0,a 放置在 b 后面。
当 a< b 时,返回值小于 0,a 和 b 不用交换位置。
- 降序排序
arrObject.sort(function(a,b){return b-a})
当 a==b 时,返回值是 0,a 和 b 不用交换位置。
当 a>b 时,返回值小于 0,a 和 b 不用交换位置。
当 a< b 时,返回值大于 0,a 放置在 b 后面。
总结
::: warning 注意 后面括号中为该方法是否改变原数组 :::
- push:用来在数组末尾推入新项(改变)
- pop:用来删除数组中的最后一项(改变)
- unshift:用来在数组开头插入新项(改变)
- shift:用来删除数组中的第一个元素(改变)
- splice:用于替换数组中的指定项(改变)
- reverse:用来将一个数组中的全部项顺序置反(改变)
- slice:用于得到子数组(不改变)
- join: 使数组转为字符串(不改变)
- concat:合并连接多个数组,返回一个新的数组(不改变)
- indexOf:搜索数组中的元素,并返回它所在的位置(不改变)
- includes:判断一个数组是否包含一个指定的值(不改变)
- sort: 在原数组上进行排序,不生成副本(改变)
- fifter: 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素(不改变)
- forEach: 对数组的每个元素执行一次给定的函数,返回值为 undefined(不改变:
forEach
不会直接改变调用它的对象,但是那个对象可能会被callback
函数改变) - map: 创建一个新数组, 新数组中的元素是原数组中的每个元素调用一次提供的函数后的返回值(不改变)
- reduce: 对数组中的每个元素执行一个由您提供的 reducer 函数(升序执行),将其结果汇总为单个返回值(不改变)
数组相关算法
数组遍历
- 求数组的和,平均数
- 求数组的最大值,最小值
// 求数组的最大值,最小值
var arr = [1, 2, 3, 45, 9, 2, 5, 67]
var max = arr[0]
var min = arr[0]
for (i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i]
} else if (arr[i] < min) {
min = arr[i]
}
}
console.log('最大值' + max + '<br>' + '最小值' + min)
数组去重
// 算法思路:准备一个空数组,遍历原数组,如果遍历到的项不在结果数组内,则推入结果数组
var arr = [1, 2, 1, 3, 4, 5, 5, 5, 6]
// 结果数组
var result = []
for (var i = 0; i < arr.length; i++) {
// include 是判断一个数组是否包含一个指定的值
if (!result.includes(arr[i])) {
// 在数组尾部插入新项
result.push(arr[i])
}
}
console.log(result)
随机样本
// 算法思路:准备一个空数组,遍历原数组,随机选择一项,推入结果数组,并且将这项删除
var arr = [1, 2, 3, 4, 5, 6, 7, 8]
// 结果数组
var result = []
for (var i = 0; i < 3; i++) {
var n = Math.floor(Math.random() * arr.length)
result.push(arr[n])
arr.splice(n, 1)
}
console.log(result)
冒泡排序
冒洵排序的核心思路是一趟一趟地进行多次项的两两比较每次都会将最小的元素排好位置,如同水中的气泡上浮一样
var arr = [1, 23, 4, 5]
for (var i = 1; i < arr.length; i++) {
// j>=i ? j代表的就是数组的下标数,总是结束在趟号那项,j=i就是最后一次比较
for (var j = arr.length - 1; j >= i; j--) {
// 内层循环负责两个数字进行比较,如果前一项大于这一项,则两项更换位置
if (arr[j - 1] > arr[j]) {
// var temp = arr[j-1]
// arr[j-1] = arr[j]
// arr[j] =temp
// 解构赋值
;[arr[j - 1], arr[j]] = [arr[j], arr[j - 1]]
}
}
}
console.log(arr)
- 4 个数字,共需要比较 3 趟,比较次数为 3+2+1=6 次
- n 个数字,共需要比较 n-1 趟,比较次数为 n(n-1)/2 次。
二维数组
以数组作为数组元素的数组,即“数组的数组“