基本操作
一维数组与二维数组互相转换
求余实现
//求余(%) 12%5返回2let baseArray = [1, 2, 3, 4, 5, 6, 7, 8]let len = baseArray.length// 假设每行显示四个let n = 4// 求余let lineNum = len % n === 0 ? len / n : Math.floor((len / n) + 1)// let lineNum = Math.ceil(len/4)let res =[]for(let i=0;i<lineNum;i++){// (0,4) (4,8)let temp = baseArray.slice(i*n,i*n+n)res.push(temp)}console.log(res) //[[1, 2, 3, 4],[5, 6, 7, 8]]
let baseArray = [1, 2, 3, 4, 5, 6, 7, 8]// 假设每行显示四个let n = 4let res = []baseArray.forEach((item,index)=>{if(!res[Math.floor(index/n)]){res[Math.floor(index/n)] =[]}res[Math.floor(index/n)].push(item)})console.log(res)// (2) [Array(4), Array(4)]// 0: (4) [1, 2, 3, 4]// 1: (4) [5, 6, 7, 8]
递归法
function change2Array(data, len, arr) {/*** @param data 一维数组* @param len 每个子数组长度* @param arr 保存的新数组*/if (data.length <= len) {arr.push(data);console.log(arr)return arr;} else {arr.push(data.splice(0, len));change2Array(data, len, arr);}}注意 splice push 都是会改变原数组的
二维数组转换为一维数组
const arr=[[1,2,3],[3,4],[5]];var newarr = [].concat.apply([],arr)console.log(newarr)call 是不可以的call 与 apply 的区别 传参的不同
let flattened = [[0,1],[1,2]].reduce(function(a,b){return a.concat(b)})console.log(flattened) //[0, 1, 1, 2]
参考文档 https://segmentfault.com/a/1190000016038640
数组与字符串的相互转换 (Array String )
1) array 转换成 string
arr.toString()
let arr = ["111","222"]console.log(arr.toString()) //111,222let arr = ["111","222",[22]]console.log(arr.toString()) //111,222,22let arr = ["111","222",{"a":111}]console.log(arr.toString()) //111,222,[object Object]
arr.join()
let arr = ["111","222",[22]]console.log(arr.join(",")) //111,222,22
2)string 转换成 array
arr.split()
let arr = "111,222"console.log(arr.split(",")) //["111", "222"]
数组降维
1.双重遍历二维数组中的每个元素并放到新数组中
function reduceDimension(arr){var reduced = [];for(var i=0;i<arr.length;i++){for(var j=0;j<arr[i].length;j++){reduced.push(arr[i][j])}}return reduced}
2.利用concat 转换
concat()不改变原数组 用于合并两个或多个数组 返回一个新数组
function reduceDimension(arr){var reduced = [];for(var i=0;i<arr.length;i++){reduced = reduced.concat(arr[i])}return reduced;}
3.利用apply 和 concat 转换
function reduceDimension(arr) {return Array.prototype.concat.apply([], arr);}
首字母大写
function ucFirst(arr){return arr.slice(0,1).toUpperCase() + arr.slice(1)}ucFirst("ahello")不能“替换”第一个字符,因为在js中字符串是不可变得但是我们可以根据已有字符串创建一个首字母大写的新字符串let newStr = str[0].toUpperCase() + str.slice(1)存在问题 如果str是空的,那么str[0] 就是 undefined 但由于undefined 没有toUpperCase()方法因此会得到一个错误存在如下两种变体:1.使用str.charAt(0) 因为它总是会返回一个字符串 (可能为空)2.为空字符添加测试function ucFirst(str) {if (!str) return str;return str[0].toUpperCase() + str.slice(1);}alert( ucFirst("john") ); // John
对数组中的图片地址处理
场景 服务器返回的图片地址 有的加上域名有的直接是图片在服务器上面的地址 需要进行处理
需要注意的是 结果是会返回一个新的数组let urlbase = "http://www.baidu.com"let a = ['1','http://www.xxx.xxx.png','3','4']let newarr = a.map(function(value,index,arr){if(value.includes('http')){return value}else{return urlbase + value}})console.log(newarr)
将数组中的字符串转换为数字
将字符串转换为数字let arr = ["1","2","3","4"]var res = arr.map(x=>Number(x))console.log(res) // [1, 2, 3, 4]console.log(typeof(res[0])) // number
取出 对象数组 中的值
实际应用 分类列表中 左边菜单的文字 在整个数据中取出重新组成单独的菜单数据
let data = [{title:"111",children:[]},{title:"111",children:[]}]var newarr = data.map(x=>x.title)console.log(newarr) //["111", "111"]
求和问题
参数不固定
reduce arguments
reduce 只适用于 数组相加
function sum(...args){return args.reduce((s,v)=>{return s+=v},0)}console.log(sum(1,2,3,4))
arguments
function sum(){// console.log(arguments)let total = null;for(let i=0;i<arguments.length;i++){//获取的每一项的结果都需要转换为数字(数学运算)let item = Number(arguments[i])//非有效数字不加if(isNaN(item)){continue}total += item}return total;}let total = sum(10,20)console.log(total)total = sum(10,20,"30")console.log(total)
验证手机号
var reg = /^1[0-9]{10}$/;
常见数组的应用
判断某个数是不是奇数
判断某个数是不是素数
数组求和
数组中的最大值
数组中的最小值
数组是否是稀松数组
什么是稀松数组:数组的元素不是连续有值。
var arr=new Array(3);arr[0] = 1arr[2] = 3其中arr[1]=undefined;
某年是否为闰年
//4年一闰,百年不闰;400年一闰
得到某年某月的天数
得到某个数字数组中出现次数最多的数字和频率
取出数组对象中的某些值重新组成一个新的数组
将下例的数据重新组成一个新的值得数组let arr = [{name: "酒水",seq: 0,type: 102},{name: "西瓜",seq: 12,type: 102}]let newArr = []arr.forEach(item=>{newArr.push({text:item.name,value:item.seq})})console.log(newArr)
生成指定范围的随机数
function getRandom(n, m) {//生成[0,10]之间,在加上 70 即可var num = Math.floor(Math.random() * (m - n + 1) + n)return num}var number = getRandom(70,80)console.log(number)
创建一个 [1…100]的数组
let arr = []// push方法for(let i = 1,len=100;i<=100;i++){arr.push(i)}//循环赋值for(let i = 1,len=100;i<=100;i++){arr[i-1]=i}// Array.from()方法 后面会有一点点的优化Array.from({length:101}, (v,k) => k)// or Array.from(Array(101), (v,k) =>k);Array.from(Array(101).keys())arr.splice(0,1)[...Array(100).keys()]// 0-> 99[...Array.from({length:100}).keys()]// 0-> 99Array.from(new Array(100).keys())// mdn 看见的 序列生成器(指定范围)const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => + (i * step));range(1,100,1)// 1-> 100Array.from({length:100},(_, i)=>1+(i)) // 1-> 100
实际应用-数组
投影数组
对某个值执行一个函数,以得到新的值,这种操作叫做投影。为了把一个数组投影成另一个数组,我们对数组中的每个元素都执行一个投影函数,然后把所有的结果收集起来,组成新的数组。
过滤数组
1.对数组中的值进行筛选过滤在重新组合
投影数组 场景: 把一个包含 video 信息的数组投影成包含{id,title}对的新数组
var newArr = message.map(item=>{return {name:item.name}})//return item.name 返回的是一个数组
2.将数组中的值变成对象的键值 形式
for in 循环方式
let obj = {}for(var item in message){obj[message[item].value] = message[item].name}console.log(obj)
map循环方式
let obj = {}var newArr = message.map(e=>{obj[e.value] = e.name})console.log(obj)
3.根据数组中的某一项值进行排序
var message = [{name: "个人待办",value: "personal_standby",order:1},{name: "流程跟踪",value: "process_tracking",order:2},{name: "应用推荐",value: "application_recommendation",order:4},{name: "最新应用",value: "latest_application",order:3},{name: "周期性应用",value: "period_application",order:5},{name: "专题推荐",value: "sbject_rommendation",order:7},{name: "收藏服务",value: "collect_service",order:6}]//function compare(p){return function(a,b){var value1 = a[p]var value2 = b[p]return value1 - value2}}var res = message.sort(compare('order'))console.log(res)
4.往数组中添加属性
map方法
var arr = message.map((item,index)=>{item.id = indexreturn item //一定要在这儿return})console.log(arr)
Object.assign()
补充 Object.assign(target, …sources)
target 目标对象 sources 源对象
下面的写法等于是把 item 与 {mess:1} 进行组合
var array2 = []message.map((item,index)=>{array2.push(Object.assign({},item,{mess1:1}))})console.log(array2)
5.对数组中重复的值进行去重
var arr2 = [{name: "name1",num: "1"},{name: "name2",num: "11"},{name: "name3",num: "12"},{name: "name4",num: "13"},{name: "name2",num: "1"},{name: "name6",num: "12"}]function arrayUnique2(arr,name){var hash = {}return arr.reduce(function(item,next){hash[next[name]] ? '': hash[next[name]] = true && item.push(next)return item},[])}console.log(arrayUnique2(arr2,"name"))//代码分析hash[next[name]] = true && item.push(next)将这个值作为一个记号进行标记
备注:上面的这个去重方法是取第一个出现的值,后面再有值的话是不会进行覆盖的。
如果要取最新的一个值该如何?
另一种方法
function unique(arr) {const res = new Map();return arr.filter((a) => !res.has(a.name) && res.set(a.name, 1))}console.log(unique(arr2))
数组去重
利用 es6 set去重
备注:set 的这种形式去重只能是 单个数组的形式,对象数组不适用。
var arr =[1,2,3,4,5,6,3,2,3]function unique(arr){return Array.from(new Set(arr))}console.log(unique(arr))//也可以另一种形式的写法var arr2 = [{name: "name1",num: "1"},{name: "name2",num: "11"},{name: "name3",num: "12"},{name: "name4",num: "13"},{name: "name6",num: "12"}]let res = [...new Set(arr2.map(item=>item.num))]
reduce 用法
文章链接
6.判断对象数组中是否存在某个对象
数组方法 some 判断
var arr = [{name: "常用"}, {name: "1"}]var obj = {name: "5"}var result = arr.some(item => {if (this.obj.name === item.name) {return true}})if (result) {console.log("已经存在")} else {this.arr.push(obj)}console.log(arr)
1.判断数组中是否存在耨个元素,indexOf()
var arr = [1,2,3,4]console.log(arr.indexOf(3)) //2console.log(arr.indexOf(8)) //-1
2.只判断情况下,可以遍历后判断对象的属性是否相同
arr.forEach(item=>{if(item.name=='Alex'){console.log('存在这个元素');}})
3.设一个flag来做判断的标识
var arr = [{name: "常用"}, {name: "1"}]var obj = {name: "1"}let flag = truearr.forEach(item=>{if(obj.name == item.name){flag = false}else{flag = true}})if(flag){arr.push(obj)}else{console.log("已存在")}console.log(arr)
7.reduce 的高级使用
var result = [{subject: 'math',score: 88},{subject: 'chinese',score: 95},{subject: 'english',score: 80}];//for 循环var sum = 0;for(var i=0; i<result.length; i++) {sum += result[i].score;}//reducevar sum = result.reduce(function(prev, cur) {return cur.score + prev;}, 0);//错误写法var sum = result.reduce(function(prev, cur) {return cur.score + prev.score ;}, 0);
这个时候,我给reduce参数添加了第二个参数。通过打印我发现设置了这个参数之后,reduce遍历便已经从第一项开始了。 这第二个参数就是设置prev的初始类型和初始值,比如为0,就表示prev的初始值为number类型,值为0,因此,reduce的最终结果也会是number类型。
https://segmentfault.com/a/1190000005921341
flat()
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
示例
扁平化嵌套数组
var arr1 = [1, 2, [3, 4]];arr1.flat();// [1, 2, 3, 4]var arr2 = [1, 2, [3, 4, [5, 6]]];arr2.flat();// [1, 2, 3, 4, [5, 6]]var arr3 = [1, 2, [3, 4, [5, 6]]];arr3.flat(2);// [1, 2, 3, 4, 5, 6]//使用 Infinity,可展开任意深度的嵌套数组var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];arr4.flat(Infinity);// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
扁平化与数组空项
flat() 方法会移除数组中的空项:
var arr4 = [1, 2, , 4, 5];arr4.flat();// [1, 2, 4, 5]
替代方案
使用 reduce 与 concat
var arr = [1, 2, [3, 4]];// 展开一层数组arr.flat();// 等效于arr.reduce((acc, val) => acc.concat(val), []);// [1, 2, 3, 4]// 使用扩展运算符 ...const flattened = arr => [].concat(...arr);
相关文章
https://github.com/mqyqingfeng/Blog/issues/36
https://juejin.cn/post/6844903805876699150#heading-5
https://www.cnblogs.com/lynn-z/p/13915539.html
数组原理
1.map
Array.prototype.myMap = function (projectionFunction) {var results = [];this.forEach(function (item) {return results.push(projectionFunction(item));});return results;};//testvar arr = [1, 2, 4, 5, 6, 7];let newArr = arr.myMap(function (x) {return x + 1;});console.log(newArr);
2.filter
为了让过滤操作更简单, 我们给数组类型添加一个 filter() 函数。 filter() 接受一个断言作为参数。 断言是这样一个函数: 它以数组中的一个元素作为参数,返回一个布尔值,表明这个元素应不应该被添加到新数组中。
Array.prototype.filter = function (predicateFunction) {var results = [];this.forEach(function (itemInArray) {//看返回是不是 truereturn predicateFunction(itemInArray) && results.push(itemInArray);});return results;};
