数组常用方法:
改变原数组 | |
Push/pop/unshift/shift | 末尾添加/删除、头部添加/删除 |
reverse | 颠倒 |
sort | 排序 |
splice(开始,删除数,添加元素) | 指定位置《前》添加或删除元素 |
不改变原数组 | |
includes | 数组是否包含指定值 |
indexOf、lastIndexOf | 判断指定字符首次、最后一次出现的位置 |
slice | 截取 |
concat | 拼接 |
join | 元素变字符串 |
下面说些不那么容易理解的或使用变化多的方法:
sort方法
首先sort是数组的一个方法,sort() 方法用于对数组的元素进行排序!然后返回排序后的数组。默认排序顺序是升序,建立在将元素转换为字符串,然后比较其UTF-16(一种编码格式)代码单元值的序列的基础上,请注意,该数组按位置排序,并且不进行任何复制!
1.默认无参数(升序)
可以验证下上面的是否正确:
let arr = [43, 2, 2, 5, 6];
arr.sort();
console.log(arr);
2.有参数(应该是个排序规则的函数)
传入的函数给定一对特定的元素a ,b 作为其两个参数,sort函数有return返回值,如果返回值大于0就是升序排列,如果是小于0就是降序!等于0就顺序不变。
a=b 保持原来位置不变
a>b 升序
a<b 降序
sort总结:
以下我自己的理解(不一定对仅个人观点):
1.sort函数是降序还是 升序完全是由排序函数决定。
2.若 return后的数
> 0 整体升序
< 0 整体降序
= 0 保持位置不变
3.如果你要排序的是数组内部是 数值 那使用参数 a,b 你就可以认为a>b(a-b>0,return a-b自然就升序 ,以下例子证明我的观点
例子1:
var asc = (a,b)=>a-b; //升序
var des= (a,b)=>b-a; //降序
var arr = [10, 44, 5, 78, 1, 99];
var arr1 = [10, 44, 5, 78, 1, 99];
console.log(arr.sort(asc));// [1, 5, 10, 44, 78, 99]
console.log(arr1.sort(des))// [99, 78, 44, 10, 5, 1]
例子2:
var asc = (a, b) => a - b < 0 ? -1 : 1 //升序
var des = (a, b) => a - b < 0 ? 1 : -1 //降低序
var arr = [10, 44, 5, 78, 1, 99];
var arr1 = [10, 44, 5, 78, 1, 99];
console.log(arr.sort(asc));// [1, 5, 10, 44, 78, 99]
console.log(arr1.sort(des))// [99, 78, 44, 10, 5, 1]
4.如果你要排序的是数组内部是 字符串 将a,b看作数组内任意两个字符串且a不等于b,根据各种条件去控制调整字符串的顺序。 以下是我项目中的例子单独提出来了:
splice()方法
作用:数组的指定位置 《前》 添加或删除元素
特点:会改变原数组
参数 | 描述 |
index | 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。 |
howmany | 必需。要删除的项目数量。如果设置为 0,则不会删除项目。 |
item1, ..., itemX | 可选。向数组添加的新项目。 |
let arr = [1, 2, 4]
arr.splice(1, 0, 23, 345) //[1,23,345,2,4]
arr.splice(1,1) //[1,345,2,4]
arr.splice(0) //[] 清空数组
slice()方法
作用:截取数组的返回新数组,就俩参数开始的位置start,结束的位置end
let arr1 = [1, 435, 546, 7]
arr1.slice(1,3) //[435,546]
arr1.slice(-2) //[546,7]
arr1.slice(1,-1) //[435,546]
arr1.slice() //[1, 435, 546, 7] //可以用来拷贝数组-并且是深拷贝
隐藏做用 ---- 拷贝数组
join()方法
作用: 数组元素变字符串
let arr1 = [1, 435, 546, 7]
arr1.join()); //1,435,546,7
arr1.join(""); //14355467
arr1.join(" "); //1 435 546 7
arr1.join("-"); //1-435-546-7
数组的深浅拷贝
写项目的时候,有时候稍不注意这个深浅拷贝就可能造成意想不到的bug,解决那对于新手来说很麻烦如果不知道问题出在哪里。
我理解的深浅拷贝:
浅拷贝:只是复制指针给另外一个变量,实际上他俩指向的是同一个地址
深拷贝:复制数组(这里先认为是数组)内的值 到另外一个地址
我们都知道js中 数组作为复杂数据类型 ,它使用赋值符号 = 去把它赋值给另一个变量是浅拷贝 , 只是将 数组的指针(地址)赋值给了新变量。其实新变量指向的还是这个数组。
如果你使用 tenpArr 进行数组操作修改了数组内的值,自然arr也会变化,因为它俩指向的是同一个数组啊。
数组中常见的深浅拷贝的操作:
说明一下,在js中深浅拷贝只针对复杂数据类型的,像 number bool undefined null string 等
不存在深浅拷贝的问题 。 string说明下:String其实是引用类型,只是编译器对其做了特殊处理(使其和基本数据类型一样)。 当然js中使用话就把他当作基本数据类型就行。
浅拷贝:
1.赋值符号 =
2.Object.assign()
深拷贝:
- JSON.parse(JSON.stringify(arr))
即可是深拷贝也可是浅拷贝
注意:下列拷贝时既可以是深拷贝也可以是浅拷贝,取决于内部元素数据类型
- slice(0)
- [...arry]
- arr.concat()
- 当然还包括for循环...遍历方式将数组内的值挨个拷贝到另一个数组中
这里说下注意点:我们知道数组遍历/过滤方法有些能返回新数组,那这些新数组就是 (新的)
实现深拷贝,比如
let newarr= arr.filter((val,index)=>{
return val.name.includes("张")
})
newarr 这数组和原来数组没任何关系,这个也可以实现深拷贝
举例:
eg1:使用扩展运算符 ... 进行数组拷贝时,无论是原始值类型还是对象,拷贝的都是值的引用。对于原始值类型,修改拷贝后的数组不会影响原始数组,因为它们是独立的值。而对于对象,修改拷贝后的数组中的对象会影响原始数组中的对象,因为它们共享同一个引用。
let originalArray = [{ a: 1 }, { b: 2 }]; let copiedArray = [...originalArray]; originalArray[0].a = 10; console.log(copiedArray); // 输出: [{ a: 10 }, { b: 2 }] let arr = [1, 3, 345, 546, 6]; let arr2 = [...arr]; arr2[1] = 234; console.log("arr", arr); // 输出: arr [1, 3, 345, 546, 6] console.log("arr2", arr2); // 输出: arr2 [1, 234, 345, 546, 6]
eg2:
//1.数组内元素为复杂数据类型 let arr = [{ tag0_description: ["一级算法Plat64,二级算法OVCrossTalk_32C,ov_crosstalk_32c_fullsize 模式校准数据;"]}]; let ary = [],ary1 = []; ary = arr.slice(0); arr[0].tag0_description[0] = "23432"; console.log(ary);// [{"tag0_description": ["23432"]}] //2.数组内元素为简单数据类型 let arr1 = [0, "23", true]; ary1 = arr1.slice(0); arr1[0] = "23432"; console.log(ary1);//[0,"23",true]
数组去重
很多方法包括循环遍历、递归等等我这里分享下感觉比较简单的(一维数组去重)
var arr = [1,2,2,3,3,4,4,5,5]
function dedupe(array) {
return [...new Set(array)]
}
console.log(dedupe(arr))
//简化代码:
[...new Set(array)] //细心的可能发现了这其实也实现了深拷贝
注意:
对于数组去重的效率问题检测
数据量1w:set这种方法效率很高,在底层是c源码实现。
数据量百万千万w:for循环结合对象属性的唯一性效率更高
Indexof():在大量的数据处理过程中会极大的降低代码性能,所以在大量数据处理的代码中,我们应该避免使用它。
数组遍历
findIndex()方法
作用:方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回 -1。
这个方法前两天遇到了,看起来和find方法很像但是还是有区别的,感觉特定情况下非常好用。
find方法为数组中每个元素执行一次callback函数,直到有一个callback返回true,返回这个元素
而findIndex是返回符合条件的第一个索引
下面是项目实例:
function func() {
let content = [
["0x0", "2", "0xf", "HL"],
["0x2", "1", "0x01", "L"],
["0x3", "4", "0xff", "4Byte_L_H"],
["0x7", "12", "0x02", "array"],
["0x13", "1", "0x01", "L"],
];
let BurnModel = "";
//大端模式数组
const RuleArryHL = ["4Byte_H_L","Float_4Byte_H_L","double_8byte_h_l","HL"];
//小端模式数组
const RuleArryLH = ["4Byte_L_H","Float_4Byte_L_H","double_8byte_l_h","LH"];
if (content.length > 0) {
// 遍历content数组,找到满足条件的元素
const tempIndex = content.findIndex((element, index) => {
// 如果BurnModel存在
if (BurnModel) {
// 如果BurnModel为"HeightLow"
if (BurnModel === "HeightLow") {
// 判断element是否包含RuleArryLH中的元素
return RuleArryLH.some((rule) => element.includes(rule));
// 如果BurnModel为"LowHeight"
} else if (BurnModel === "LowHeight") {
// 判断element是否包含RuleArryHL中的元素
return RuleArryHL.some((rule) => element.includes(rule));
}
// 如果BurnModel不存在
} else {
// 如果RuleArryHL中的元素包含element
if (RuleArryHL.some((rule) => element.includes(rule))) {
BurnModel = "HeightLow";
// 如果RuleArryLH中的元素包含element
} else if (RuleArryLH.some((rule) => element.includes(rule))) {
BurnModel = "LowHeight";
}
}
// 返回false
return false;
});
// 如果找到满足条件的元素
if (tempIndex !== -1) {
BurnModel = "mixModel";
}
}
console.log("BurnModel:", BurnModel);
}
func();