数组
JavaScript数组、数组排序、常用API、数组去重、常见算法题
一、数组
数组的概念
数组是指一组数据的集合,其中的每个数据被称作为元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
创建数组
数组的创建方式
JS中创建数组的两种方式:
- 利用new创建数组
- 利用数组字面量创建数组
利用new创建数组
var 数组名=new Array();
var arr=new Array(); //创建一个新的空数组
利用数组字面量创建数组
// 1、利用数组字面量方式创建空的数组
var 数组名 = [];
// 2、使用数组字面量方式创建带初始值的数值
var 数组名 = ['小白', '小黑', '大黄'];
- 数组的字面量是方括号[ ]
- 声明数组并赋值称为数组的初始化
- 这种字面量方式也是我们以后最多使用的方式
数组的元素类型
数组中可以存放任意类型的数据,例如字符串,数字,布尔值等
var arrStus = ['小白', 12, true, 28.9];
// 1、数组(Array):就是一组数据的集合,存储在单个变量下的优雅方式
// 2、利用new 创建数组
var arr = new Array(); //创建了一个空的数组
// 3、利用数组字面量方式创建空的数组
var arr = []; //创建了一个空的数组
var arr1 = ['小白', '小黑', '大黄', 1, 2, true];
// 4、我们数组里面的数据一定用逗号分隔
// 5、数组里面的数据 比如1,2 我们称为数组元素
获取数组元素
数据的索引
索引(小标):用来访问数组元素的序号(数组下标从0开始)
数组可以通过索引来访问、设置、修改对应的数组元素,我们可以通过“数组名[索引]”的形式来获取数组中的元素。
这里的访问就是获取得到的意思
遍历数组
遍历:就是把数组中的每个元素从头到尾都访问一次(类似学生点名)。
// 遍历数组:就是把数组的元素从头到尾访问一次
var arr = ['red', 'green', 'blue'];
for (var i = 0; i < 3; i++) {
console.log(arr[i]);
}
// 1、因为我们的数组索引号从0开始,所以 i 必须从 0开始 i<3
// 2、输出的时候arr[i] i 计数器当索引号来用
数组的长度
使用“数组名:length”可以访问数组元素的数量(数组长度)
// 数组长度 数组名.length
var arr = ['关羽', '张飞', '马超', '赵云', '黄忠', '刘备', '姜维'];
for (var i = 0; i < 7; i++) {
console.log(arr[i]);
}
console.log(arr.length);
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
// 1.数组的长度是元素个数 不要跟索引号混淆
// 2.arr.length动态监测数组元素的个数
数组中新增元素
可以通过修改length长度以及索引号增加数组元素
1. 通过修改length长度新增数组元素
- 可以通过修改length长度来实现数组扩容的目的
- length属性是可读写的
// 1.新增数组元素 修改length长度
var arr = ['red', 'green', 'blue'];
console.log(arr.length);
arr.length = 5; //把我们数组的长度修改为 5 里面应该有5个元素
console.log(arr);
console.log(arr[3]); //undefined
console.log(arr[4]); //undefined
其中索引号3、4的空间没有给值,就是声明变量未给值,默认值就是undefined
通过修改数组索引新增数组元素
- 可以通过修改数组索引的方式追加数组元素
- 不能直接给数组名赋值,否则会覆盖掉以前的数据
// 2.新增数组元素 修改索引号 追加数组元素
var arr1 = ['red', 'green', 'blue'];
arr1[3] = 'pink';
console.log(arr1);
arr1[4] = 'hotpink';
console.log(arr1);
arr1[0] = 'yellow'; //这里是替换原来的数组元素
console.log(arr1);
arr1 = '有点意思';
console.log(arr1); //不要直接给 数组名赋值 否则里面的数组元素都没有了
翻转数组
// 将数组['red','green','blue','pink','purple']的内容反过来存放
// 1、声明一个新数组newArr
// 2、把旧数组索引号第4个取过来(arr.length -1),给新数组索引号第0个元素(newArr.length)
// 3、我们采取递减的方式 i--
var arr = ['red', 'green', 'blue', 'pink', 'purple'];
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i]
}
console.log(newArr);
二、数组方法
方法汇总
- pop() 从数组中删除最后一个元素
- push() 方法(在数组结尾处)向数组添加一个新的元素
- shift() 方法会删除首个数组元素,并把所有其他元素“位移”到更低的索引。
- unshift() 方法(在开头)向数组添加新元素,并“反向位移”旧元素
- splice() 方法可用于向数组添加新项
- sort() 方法用于对数组的元素进行排序。
- reverse() 方法反转数组中元素的顺序。
- concat() 方法通过合并(连接)现有数组来创建一个新数组
- slice() 方法用数组的某个片段切出新数组。
- isArray() 这个方法主要用来判断变量是否是一个js数组。
- forEach() 这个方法主要用于遍历数组。
- reduce() 主要是对数组中的每个元素执行函数,生成一个值。例如,下面求数组元素的总和。
- indexOf() 主要用于在数组中查找元素,并把元素的位置返回来。
- filter() 与map方法类似,也是对数组中的每个元素执行相同的函数,将结果组合成一个新数组。
- map() 主要用于对每个数组里面的元素执行相同的函数来创建新的数组。
- find() 返回通过测试(函数内判断)的数组的第一个元素的值。
- some() 用于检测数组中的元素是否满足指定条件(函数提供)。
- every() 主要用于检查数组中每个元素是否符合函数的条件,如果其中有一个不符合,则返回false
push()、pop()、shift()、unshift()、splice()、sort()、reverse()方法会改变原数组
filter()、concat()、slice()方法会返回新数组
pop()
pop() 从数组中删除最后一个元素
实现原理
Array.prototype.pop = function () {
//this :当前实例
var num = this[this.length-1];
this.length--;
return num;
};
console.log(ary.pop());
console.log(ary);
push()
push() 方法(在数组结尾处)向数组添加一个新的元素
实现原理
Array.prototype.push=function () {
for (var i = 0; i < arguments.length; i++){
this[this.length] = arguments[i]
}
return this.length;
};
console.log(ary.push(1, 2, 3));
console.log(ary);
shift()
shift() 方法会删除首个数组元素,并把所有其他元素“位移”到更低的索引。
实现原理
Array.prototype.shift = function () {
var num=this[0];
for(var i = 1; i < this.length; i++){
this[i-1]=this[i];
}
this.length--;
return num;
};
console.log(ary.shift());
console.log(ary);
unshift()
unshift() 方法(在开头)向数组添加新元素,并“反向位移”旧元素
实现原理
Array.prototype.unshift = function () {
var ary = [...arguments,...this];
this.length = ary.length;
for(var i = 0; i < ary.length; i++){
this[i] = ary[i];
}
return ary.length;
};
Array.prototype.unshift = function () {
var str="";
for(var i = 0; i < arguments.length; i++){
if(typeof arguments[i] == "string"){
str += "'" + arguments[i] + "',";
}else {
str += arguments[i] + ",";
}
}
for(var i = 0; i < this.length;i++){
if(typeof this[i] == "string"){
str += "'" + this[i] + "',"
} else {
str += this[i] + ","
}
}
var ary = eval("["+str+"]");
this.length=ary.length;
for(var i = 0; i < ary.length; i++){
this[i] = ary[i];
}
return ary.length;
};
ary.unshift("哈哈","嘿嘿");
console.log(ary);
splice()
splice() 方法可用于向数组添加新项
concat()
concat() 方法通过合并(连接)现有数组来创建一个新数组
slice()
slice() 方法用数组的某个片段切出新数组。
reverse()
reverse() 方法反转数组中元素的顺序。
语法
array.reverse()
注释:reverse() 方法将改变原始数组。
filter()
与map方法类似,也是对数组中的每个元素执行相同的函数,将结果组合成一个新数组。
用法
let arr=[2,4,6,8];
let arr1 = arr.filter(function(item){
return item > 5
})
console.log(arr1) //[6,8]
实现原理
Array.prototype.filter1 = function (fn) {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
let newArr = [];
for(let i = 0; i < this.length; i++) {
fn(this[i]) && newArr.push(this[i]);
}
return newArr;
}
let arr = [2,4,6,8];
let arr1 = arr.filter1(function(item){
return item>5
})
console.log(arr1) //[6,8]
map()
主要用于对每个数组里面的元素执行相同的函数来创建新的数组。
用法
let arr = ['bob', 'grex', 'tom'];
let arr1 = arr.map(function(item) {
return `<li>${item}</li>`;
});
console.log(arr1); //[ '<li>bob</li>', '<li>grex</li>', '<li>tom</li>' ]
实现原理
Array.prototype.map = function(fn) {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
let newArr = [];
for (let i = 0; i < this.length; i++) {
newArr.push(fn(this[i]))
};
return newArr;
}
find()
返回通过测试(函数内判断)的数组的第一个元素的值。为数组中的每个元素都调用一次函数执行
- 当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。
- 如果没有符合条件的元素返回 undefined
注意: find() 对于空数组,函数是不会执行的。find() 并没有改变数组的原始值。
用法
let arr = [1,2,3];
let arr1 = arr.find(function (item) {
return item >= 2
});
console.log( arr5); //2
实现原理
Array.prototype.find = function(fn) {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
for (let i = 0; i < this.length; i++) {
if (fn(this[i])) return this[i]
}
}
some()
用于检测数组中的元素是否满足指定条件(函数提供)。会依次执行数组的每个元素
- 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
- 如果没有满足条件的元素,则返回false。
注意: some() 对于空数组,函数是不会执行的。some() 并没有改变数组的原始值。
用法
let arr = [2, 4, 6, 8];
let flag = arr.some(function(item) {
return item > 5
});
console.log(flag); //true
实现原理
Array.prototype.some=function (fn) {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
for(let i = 0; i < this.length; i++){
if(fn(this[i])) {
return true
}
}
return false
};
every()
用于检测数组所有元素是否都符合指定条件(通过函数提供)。使用指定函数检测数组中的所有元素
- 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
- 如果所有元素都满足条件,则返回 true。
注意: every() 对于空数组,函数是不会执行的。every() 并没有改变数组的原始值。
用法
let arr = [2, 4, 6, 8];
let flag = arr.every(function(item) {
return item > 5
});
console.log(flag); //false
实现原理
Array.prototype.every = function (fn) {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function`);
}
for(let i = 0; i < this.length; i++){
if(!fn(this[i])) {
return false
}
}
return true
};
是否改变原数组
以下方法会改变原数组
var arr = []
arr.splice()
arr.reverse()
arr.sort()
arr.push()
arr.pop()
arr.unshift()
arr.shift()
// es6方法
arr.fill()
arr.copyWithin()
以下方法不会改变原数组
var arr = []
arr.slice()
arr.map()
arr.forEach()
arr.every()
arr.some()
arr.filter()
arr.reduce()
arr.entries()
arr.find()
arr.concat('1',['2','3']) //[1,2,3]
三、数组排序
数组排序
sort() 方法以字母顺序对数组进行排序:
默认地,sort() 函数按照字符串顺序对值进行排序。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
console.log(fruits)
reverse() 方法反转数组中的元素。
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort(); // 对 fruits 中的元素进行排序
fruits.reverse(); // 反转元素顺序
默认地,sort() 函数按照字符串顺序对值进行排序。
该函数很适合字符串("Apple" 会排在 "Banana" 之前)。
不过,如果数字按照字符串来排序,则 "25" 大于 "100",因为 "2" 大于 "1"。
正因如此,sort() 方法在对数值排序时会产生不正确的结果。
我们通过一个比值函数来修正此问题:
var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a - b});
冒泡排序
冒泡排序:是一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小)
// 冒泡排序
var arr = [5, 4, 3, 2, 1];
for (var i = 0; i < arr.length - 1; i++) { //外面循环管趟数
for (var j = 0; j <= arr.length - i - 1; j++) { //里面的循环管每一趟交换的次数
// 内部交换2个变量的值 前一个和后面一个数组元素相比较
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr);
JS(数组、字符串,常用API)
API定义
API:JS中预定义好的一些函数或者方法
数组API
toString() 将数组转为字符串,元素之间用逗号隔开
join() 将数组转为字符串,可以指定元素之间的分隔符
reverse() 翻转数组元素,原数组会发生变化
sort() 对数组进行排序,默认是按照首个字符的Unicode码排列,原数组会发生变化
shift() 删除数组开头的一个元素,返回删除的元素,原数组会发生变化
pop() 删除数组末尾的一个元素,返回删除的元素,原数组会发生变化
unshift() 在数据的开头添加元素,返回数组的长度,原数组会发生变化
push() 在数据的末尾添加元素,返回数组的长度,原数组会发生变化
indexOf() 查看数组中是否含有某个元素,返回下标,如果找不到返回-1
slice(start, end) 截取数组元素,start开始的下标,end结束的下标,不包括end本身,end为空截取 到最后,下标为负数表示倒数,返回截取到的元素。
splice(start, count, v1,v2) 删除数组元素,start开始的下标,count删除的长度,count为空删除到最 后,下标为负数表示倒数,v1,v2表示删除后补充的元素,返回删除的元素,原数组会发生变化。
concat() 方法用于连接两个或多个字符串。
every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
字符串API
length 获取字符串的长度
charAt() 获取下标对应的字符,也可以使用数组的写法 字符串[下标]
indexOf() 查找字符串中是否含有某个字符串,返回满足条件的第一个的下标,找不到返回-1
lastIndexOf() 查找字符串中是否含有某个字符串,返回满足条件的最后一个的下标,找不到返回-1
taosang#tedu.cn
toUpperCase() 英文字母转大写
toLowerCase() 英文字母转小写
所有的字符串对象下的API都不会对原来的字符串产生任何影响,会生成一个新的字符串
slice(start, end) 截取字符串,start开始的下标,end结束的下标,不包括end本身,end为空截取到 最后,如果下标为负数表示倒数
substr(start,count) 截取字符串,start开始的下标,count截取的长度,count为空截取到最后,下标为 负数表示倒数
split() 将字符串转为数组
Number对象API
new Number() 将数据转为数值,返回对象
Number() 将数据转为数值,返回是数值
toFixed(n) 保留小数点后n位
toString() 将数值转为字符串
Boolean对象
new Boolean() 将数据转为布尔型,返回对象
Boolean() 将数据转为布尔型,返回布尔型
!!数据 将数据隐式转换为布尔型
Math对象API
PI 圆周率
abs() 获取绝对值
ceil() 向上取整
floor() 向下取整
round() 四舍五入取整
pow(x,y) 次方/次幂
max() 获取一组数字最大值
min() 获取一组数字最小值
random() 获取随机 >=0 <1
Date对象API
getFullYear()/getMonth()/getDate()
月份的范围是0~11,代表1~12月
getHours()/getMinutes()/getSeconds()/getMilliseconds() 获 取毫秒
getDay() 获取星期 0~6 对应 星期日~星期六
getTime() 获取距离计算机元年的毫秒数
四、数组去重
最简单方法(indexOf 方法)
实现思路:新建一个数组,遍历要去重的数组,当值不在新数组的时候(indexOf 为 -1)就加入该新数组中;
function unique(arr){
var newArr = [];
for(var i = 0; i < arr.length; i++){
if(newArr.indexOf(arr[i]) == -1){
newArr.push(arr[i])
}
}
return newArr;
}
var arr = [1,2,2,3,4,4,5,1,3];
var newArr = unique(arr);
console.log(newArr);
优化遍历数组法
实现思路:双层循环,外循环表示从0到arr.length,内循环表示从i+1到arr.length,
将没重复的右边值放入新数组。(检测到有重复值时终止当前循环同时进入外层循环的下一轮判断)
function unique(arr){
var newArr = [];
for(var i = 0; i < arr.length; i++){
for(var j = i+1; j < arr.length; j++){
if(arr[i] == arr[j]){
++i;
}
}
newArr.push(arr[i]);
}
return newArr;
}
var arr = [1,2,2,3,5,3,6,5];
var newArr = unique(arr);
console.log(newArr);
利用对象的属性不能相同的特点进行去重(推荐使用)
实现思路:
- 1.创建一个新的数组存放结果
- 2.创建一个空对象
- 3.for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,同时把这个元素的内容作为对象的一个属性,并赋值为1,存入到第2步建立的对象中。
function unique(arr){
var res = [];
var obj = {};
for(var i = 0; i < arr.length; i++){
if( !obj[arr[i]] ){
obj[arr[i]] = 1;
res.push(arr[i]);
}
}
return res;
}
var arr = [1,2,2,3,5,3,6,5];
var res = unique(arr)
console.log(res );
ES6 数组去重
利用 ES6的 Set 方法。
function unique(arr){
//Set数据结构,它类似于数组,其成员的值都是唯一的
return Array.from(new Set(arr)); // 利用Array.from将Set结构转换成数组
}
var arr = [1,2,2,3,5,3,6,5];
var res = unique(arr)
console.log(res);
六、常见算法题
统计字符串中出现最多的字母
/**
* 获取字符串中出现次数最多的字母
* @param {String} str
*/
function getChar(str) {
if (typeof str !== 'string') return // 判断参数是否为字符串
const obj = new Object() // 键为字母,值为次数
for (let i = 0; i < str.length; i ++) { // 遍历字符串每一个字母
let char = str.charAt(i) // 当前字母
obj[char] = obj[char] || 0 // 保证初始值为0
obj[char] ++ // 次数加1
}
let maxChar // 存储字母
let maxNum = 0 // maxChar字母对应的次数
for(let key in obj) { // 遍历obj
if (obj[key] > maxNum) {
maxChar = key // 比较后存储次数多的字母
maxNum = obj[key] // 以及它对应的次数
}
}
return maxChar // 返回结果
}
let str = 'aabbbccdd'
console.log('出现次数最多的字母为:' + getChar(str))
字符串反序
首先将字符串序列化成数组,通过数组方法对数组反序,最后把数组转换成字符串。
'say I love U'.split('').reverse().join('') // U evol I yas