js 数组操作
js 数组操作
在开发中,数组的使用场景非常多,平日中也涉及到很多数组相关操作,对一些常见的操作方法进行总结和收藏,在开发中就能信手拈来,大大提高开发效率。
常用操作
1、join();
用法:将数组中的所有元素都转化为字符串,并连接在一起;
var a = [1,2,3,4];
console.log(a.join('-')); //1-2-3-4
2、reverse()
用法:将数组中的元素颠倒顺序.
var a = [1,2,3,4];
console.log(a.reverse()); // [4, 3, 2, 1]
3、concat()
用法:拼接多个数组,并返回全新的数组,原数组不受影响;
var a = [1,2];
var b = [10,20];
console.log(a.concat(b)); //[1, 2, 10, 20]
4、slice()
用法:截取数组生成新数组,原数组不受影响;
返回的数组**第一个参数指定的位置(包含)和第二个参数指定的位置(不包含)**之间的所有元素,如果指定参数为负数,则从数组的最后一个元素开始,如果只有一个参数,则表示到数组的末尾;
var aa = [1,2,3,4,5,6];
console.log(aa.slice(2)); //[3,4,5,6]
console.log(aa.slice(2,8)); //[3,4,5,6] 超过最大长度,只显示到最后结果
console.log(aa.slice(2,5)); //[3,4,5]
console.log(aa.slice(2,-1)); //[3,4,5] 相对于倒数第一个之前
console.log(aa.slice(2,-2)); //[3,4] 相对于倒数第二个之前
console.log(aa.slice(3)); //[4,5,6] 一个参数从第三个到最后
console.log(aa.slice(-2));//[5,6] 一个参数负值从倒数第二个到最后
5、splice()
用法:从数组中添加、删除项目,然后返回被删除的项目。该方法会改变原始数组,
语法:
array.splice(index,howmany,item1,...,itemX)
var aa = [1,2,3,4,5,6];
console.log(aa.splice(4)); //[5,6] 返回删除后的数组
aa; // [1,2,3,4]
console.log(aa.splice(2,2)); //[3,4] 从第二位起删除两个元素
aa; //[1,2]
console.log(aa.splice(1,0,7,8)); //[]从第一位起删除0个元素,添加7,8到原数组
aa;//[1,7,8,2]
6、push()
用法:在数组的末尾添加一个或者多个元素,并返回新的数组长度;
8、shift()
用法:把数组的第一个元素从其中删除,并返回第一个元素的值
说明:如果数组是空的,那么 shift() 方法将不进行任何操作,返回 undefined 值。请注意,该方法不创建新数组,而是直接修改原有的 arrayObject。该方法会改变原数组的长度
;
9、unshift()
用法:相数组开头添加一个或多个元素,并返回新长度
;
10、toString()
用法:可把一个逻辑值或数组转换为字符串,并返回结果。
console.log( [1,2,3].toString() ); //1,2,3
console.log( typeof(true.toString()) ); //string
11、toLocalString()
用法:使用地区特定的分隔符把生成的字符串连接起来,形成一个字符串。
var date = new Date();
console.log(date.toString()); // Wed May 27 2020 11:20:04 GMT+0800 (中国标准时间)
console.log(date.toLocaleString()); //2020/5/27 上午11:20:04
12、indexOf()
用法:返回某个指定的字符在字符串中首次出现的位置。没查到返回-1
console.log(['a','b','c','d'].indexOf('a')); //1
13、lastIndexOf()
用法:从数组的末尾开始查找,返回某个指定字符串首次出现的位置(即索引值),索引值永远是正序的索引值,没有查找到返回-1
console.log(['a','b','c','d'].lastIndexOf('d')); //4
14、forEach()
定义:从头至尾遍历数组,为每个元素调用指定函数,改变元素的同时数组内的相应值也会改变,输入为一个待遍历函数,函数的参数依次为:数组元素、元素的索引、数组本身,没有返回值
let a = ['a','b','c','d',];
a.forEach(function(e,index,arr){
console.log(e); //单个元素
console.log(index); //该元素的索引值
console.log(arr); //数组
})
15、map()
定义:用的数组的每一个元素传递给指定的函数,并返回一个新数组 ,不修改原数组。
var arr = [2,3,4,5,6];
var bb= arr.map(function(x){
return x*x;
});
console.log(bb); // [4, 9, 16, 25, 36]
16、filter()
定义:过滤功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。函数的参数依次为:数组元素、元素的索引、数组本身,
注:可以去重
var a = [1,2,3,4,5,6,3,1];
a.filter(function(e,i,selfArr){
return selfArr.indexOf(e) == i;
});
//[1, 2, 3, 4, 5, 6]
17、every()和some()
every() 判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。类似&&
some() 判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。类似 ||
var arr = [1, 2, 3, 4, 5, 6];
arr.every(x=>x>0);//return true;
arr.every(x=>x>5);//return false;
arr.some(x=>x>5);//return true;
18、reduce()和reduceRight()
reduce() 两个参数:函数和递归的初始值。从数组的第一项开始,逐个遍历到最后
reduceRight() 从数组的最后一项开始,向前遍历到第一项
//可以用reduce快速求数组之和
var arr=[1,2,3,4];
arr.reduce(function(a,b){
return a+b;
}); //10
19、sort()
定义:用于对数组的元素进行排序。在原数组上面进行修改,没有返回值
var a = [6,4,2,8,22];
a.sort(function(x,y){
return x - y;
}) //小->大
console.log(a); //[2, 4, 6, 8, 22]
a.sort(function(x,y){
return y - x;
}) //大->小
console.log(a); [22, 8, 6, 4, 2]
var b = [ //数组对象去重
{index:2},
{index:7},
{index:9},
{index:1},
]
b.sort(function(x,y){
return x.index - y.index;
})
console.log(b); //b = [ {index:1},{index:2},{index:7},{index:9}]
随机排序
1、生成随机数
遍历数组,每次循环都随机一个在数组长度范围内的数,并交换本次循环的位置和随机数位置上的元素
function randomSort1(arr) {
for (let i = 0, l = arr.length; i < l; i++) {
let rc = parseInt(Math.random() * l)
// 让当前循环的数组元素和随机出来的数组元素交换位置
const empty = arr[i]
arr[i] = arr[rc]
arr[rc] = empty
}
return arr
}
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 下面两次的结果肯定是不一样的;
console.log(randomSort1(arr1))
console.log(randomSort1(arr1))
2、生成新数组
- 申明一个新的空数组,利用 while 循环,如果数组长度大于 0,就继续循环;
- 每次循环都随机一个在数组长度范围内的数,将随机数位置上的元素 push 到新数组里,
- 并利用 splice(对 splice 不太理解的同学可以看这里)截取出随机数位置上的元素,同时也修改了原始数组的长度;
function randomSort2(arr) {
var mixedArr = []
while (arr.length > 0) {
let rc = parseInt(Math.random() * arr.length)
mixedArr.push(arr[rc])
arr.splice(rc, 1)
}
return mixedArr
}
// 例子
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(randomSort2(arr1))
3、 arr.sort
- 如果 compareFunction(a, b)的返回值 小于 0 ,那么 a 会被排列到 b 之前;
- 如果 compareFunction(a, b)的返回值 等于 0 ,那么 a 和 b 的相对位置不变;
- 如果 compareFunction(a, b)的返回值 大于 0 ,那么 b 会被排列到 a 之前;
function randomSort3(arr) {
arr.sort(function (a, b) {
return Math.random() - 0.5
})
return arr
}
// 例子
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(randomSort3(arr1))
数组对象排序
1、单个属性排序
function compare(property) {
return function (a, b) {
let value1 = a[property]
let value2 = b[property]
return value1 - value2
}
}
let arr = [
{ name: 'zopp', age: 10 },
{ name: 'gpp', age: 18 },
{ name: 'yjj', age: 8 },
]
console.log(arr.sort(compare('age')))
2、多个属性排序
var s = [
{ first: 'Jo', last: 'Be' },
{ first: 'Moe', last: 'Ho' },
{ first: 'Jo', last: 'De' },
{ first: 'Sh', last: 'Ho' },
{ first: 'La', last: 'Fi' },
{ first: 'Cu', last: 'Ho' }
];
function by(name, minor) {
return function (o, p) {
var a, b;
if (typeof o === 'object' && typeof p === 'object' && o && p) {
a = o[name];
b = p[name];
if (a === b) {
return typeof minor === 'function' ? minor() : 0;
}
if (typeof a === typeof b) {
return a < b ? -1 : 1;
}
return typeof a < typeof b ? -1 : 1;
} else {
// throw {
// name: 'Error',
// message: 'XXXXXXX '
// };
}
};
};
console.log(s.sort(by('last', by('first'))));
// [ { first: 'Jo', last: 'Be' },
// { first: 'Jo', last: 'De' },
// { first: 'La', last: 'Fi' },
// { first: 'Moe', last: 'Ho' },
// { first: 'Sh', last: 'Ho' },
// { first: 'Cu', last: 'Ho' } ]
数组扁平化
1、调用 ES6 中的 flat 方法
ary = arr.flat(Infinity)
console.log([1, [2, 3, [4, 5, [6, 7]]]].flat(Infinity))
2、普通递归
let result = []
let flatten = function (arr) {
for (let i = 0; i < arr.length; i++) {
let item = arr[i]
if (Array.isArray(arr[i])) {
flatten(item)
} else {
result.push(item)
}
}
return result
}
let arr = [1, 2, [3, 4], [5, [6, 7]]]
console.log(flatten(arr))
3、利用 reduce 函数迭代
function flatten(arr) {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flatten(cur) : cur)
}, [])
}
let arr = [1, 2, [3, 4], [5, [6, 7]]]
console.log(flatten(arr))
4、扩展运算符
function flatten(arr) {
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
let arr = [1, 2, [3, 4], [5, [6, 7]]]
console.log(flatten(arr))
数组去重
1、利用数组的 indexOf 下标属性来查询
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
}
console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
2、先将原数组排序,在与相邻的进行比较,如果不同则存入新数组。
function unique(arr) {
var formArr = arr.sort()
var newArr = [formArr[0]]
for (let i = 1; i < formArr.length; i++) {
if (formArr[i] !== formArr[i - 1]) {
newArr.push(formArr[i])
}
}
return newArr
}
console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
3、利用对象属性存在的特性,如果没有该属性则存入新数组。
function unique(arr) {
var obj = {}
var newArr = []
for (let i = 0; i < arr.length; i++) {
if (!obj[arr[i]]) {
obj[arr[i]] = 1
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
4、利用数组原型对象上的 includes 方法。
function unique(arr) {
var newArr = []
for (var i = 0; i < arr.length; i++) {
if (!newArr.includes(arr[i])) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
5、利用数组原型对象上的 filter 和 includes 方法。
function unique(arr) {
var newArr = []
newArr = arr.filter(function (item) {
return newArr.includes(item) ? '' : newArr.push(item)
})
return newArr
}
console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
6、利用 ES6 的 set 方法。
function unique(arr) {
return Array.from(new Set(arr)) // 利用Array.from将Set结构转换成数组
}
console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
根据属性去重
方法一
function unique(arr) {
const res = new Map()
return arr.filter((item) => !res.has(item.productName) && res.set(item.productName, 1))
}
方法二
function unique(arr) {
let result = {}
let obj = {}
for (var i = 0; i < arr.length; i++) {
if (!obj[arr[i].key]) {
result.push(arr[i])
obj[arr[i].key] = true
}
}
}
交集/并集/差集
1、includes 方法结合 filter 方法
let a = [1, 2, 3]
let b = [2, 4, 5]
// 并集
let union = a.concat(b.filter((v) => !a.includes(v)))
// [1,2,3,4,5]
// 交集
let intersection = a.filter((v) => b.includes(v))
// [2]
// 差集
let difference = a.concat(b).filter((v) => !a.includes(v) || !b.includes(v))
// [1,3,4,5]
2、ES6 的 Set 数据结构
let a = new Set([1, 2, 3])
let b = new Set([2, 4, 5])
// 并集
let union = new Set([...a, ...b])
// Set {1, 2, 3, 4,5}
// 交集
let intersect = new Set([...a].filter((x) => b.has(x)))
// set {2}
// 差集
let difference = new Set([...a].filter((x) => !b.has(x)))
// Set {1, 3, 4, 5}
数组求和
1、万能的 for 循环
function sum(arr) {
var s = 0
for (var i = arr.length - 1; i >= 0; i--) {
s += arr[i]
}
return s
}
sum([1, 2, 3, 4, 5]) // 15
2、递归方法
function sum(arr) {
var len = arr.length
if (len == 0) {
return 0
} else if (len == 1) {
return arr[0]
} else {
return arr[0] + sum(arr.slice(1))
}
}
sum([1, 2, 3, 4, 5]) // 15
3、ES6 的 reduce 方法
function sum(arr) {
return arr.reduce(function (prev, curr) {
return prev + curr
}, 0)
}
sum([1, 2, 3, 4, 5]) // 15
类数组转化
1、Array 的 slice 方法
let arr = Array.prototype.slice.call(arguments)
2、ES6 的 Array.from()
let arr = Array.from(arguments)
3、扩展运算符...
let arr = [...arguments]
数组上下移动
function swapItems(arr, index1, index2) {
arr[index1] = arr.splice(index2, 1, arr[index1])[0]
return arr
}
function up(arr, index) {
if (index === 0) {
return
}
this.swapItems(arr, index, index - 1)
}
function down(arr, index) {
if (index === this.list.length - 1) {
return
}
this.swapItems(arr, index, index + 1)
}
数组转化为树形结构
将如下数据转化为树状结构
let arr = [
{
id: 1,
name: '1',
pid: 0,
},
{
id: 2,
name: '1-1',
pid: 1,
},
{
id: 3,
name: '1-1-1',
pid: 2,
},
{
id: 4,
name: '1-2',
pid: 1,
},
{
id: 5,
name: '1-2-2',
pid: 4,
},
{
id: 6,
name: '1-1-1-1',
pid: 3,
},
{
id: 7,
name: '2',
},
]
实现方法
function toTree(data, parentId = 0) {
var itemArr = []
for (var i = 0; i < data.length; i++) {
var node = data[i]
if (node.pid === parentId) {
var newNode = {
...node,
name: node.name,
id: node.id,
children: toTree(data, node.id),
}
itemArr.push(newNode)
}
}
return itemArr
}
console.log(toTree(arr))
/**
* [toTree 构建层级树]
* @param {[array]} data
* @return {[array]}
*/
function toTree(data) {
// 删除 所有 children,以防止多次调用
data.forEach(function (item) {
delete item.children;
});
// 将数据存储为 以 id 为 KEY 的 map 索引数据列
let map = {};
data.forEach(function (item) {
map[item.id] = item;
});
let val = [];
data.forEach(function (item) {
// 以当前遍历项,的pid,去map对象中找到索引的id
let parent = map[item.pid];
// 好绕啊,如果找到索引,那么说明此项不在顶级当中,那么需要把此项添加到,他对应的父级中
if (parent) {
(parent.children || (parent.children = [])).push(item);
} else {
//如果没有在map中找到对应的索引ID,那么直接把 当前的item添加到 val结果集中,作为顶级
val.push(item);
}
});
return val;
};
其他
/**
* [getIdsInArr 查询arr 里 含有的 ids]
* @param string ids
* @param array arr
* @return [array] [含有ids的数据]
*/
function getIdsInArr(ids = '', arr = []) {
ids = ids.split(',');
temp = [];
ids.forEach(v => {
arr.forEach(vv => {
if (v == vv['id']) {
temp.push(vv);
}
});
});
return temp;
};
/**
* [getAllChildID 根据数组 id 获取所有子id]
* @param array arr
* @param int id
* @return {Array} res
*/
function getAllChildID(arr, id, res = []) {
arr.forEach(item => {
if (item.pid == id) {
res.push(item.id);
this.getAllChildID(arr, item.id, res);
}
});
return res;
};
/**
* [getParents 根据子id,获取所有父类]
* @param {[array]} arr [description]
* @param {[int]} myid [description]
* @param {[boolean]} withself [description]
* @return {[arr]} [返回自身和父类]
*/
function getParents(arr, myid, withself = false, newarr = []) {
let pid = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i].id == myid) {
if (withself) {
newarr.unshift(arr[i]);
}
pid = arr[i].pid;
break;
}
}
if (pid) {
this.getParents(arr, pid, true, newarr);
}
return newarr;
};
/**
* [difference 两个数组取差集]
* @param array arr1
* @param array arr2
* @return array
*/
function difference(arr1, arr2) {
var diff = [];
var tmp = arr2;
arr1.forEach(function (val1, i) {
if (arr2.indexOf(val1) < 0) {
diff.unshift(val1);
} else {
tmp.splice(tmp.indexOf(val1), 1);
}
});
return diff.concat(tmp);
};
// JavaScript_ JS数组求并集,交集和差集 (ES7/ES6/ES5)
// https://blog.csdn.net/u010003835/article/details/79042135