zoukankan      html  css  js  c++  java
  • 前端常用算法集合,持续更新...

    myFn(obj){   //深度遍历替换
        for(let i in obj) {
         console.log(i + ': ' + obj[i]);
          if (i == 'navigator_url') {
            obj[i] = obj[i].replace("goods_list", "goods_list/index");
            console.log(obj[i])
          }
          if (typeof (obj[i]) == 'object') {
            // 判断用户是否要继续迭代   
            this.myFn(obj[i]);
          }
        }
       return obj;
      }

    对象数据格式化

    面试阿里的一道笔试题,问题是如果服务器返回了嵌套的对象,对象键名大小写不确定,如果统一让键名小写。

    let obj = {
        a: '1',
        b: {
            c: '2',
            D: {
                E: '3'
            }
        }
    }
    转化为如下:
    let obj = {
        a: '1',
        b: {
            c: '2',
            d: {
                e: '3'
            }
        }
    }
    // 代码实现
    function keysLower(obj) {
        let reg = new RegExp("([A-Z]+)", "g");
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                let temp = obj[key];
                if (reg.test(key.toString())) {
                    // 将修改后的属性名重新赋值给temp,并在对象obj内添加一个转换后的属性
                    temp = obj[key.replace(reg, function (result) {
                        return result.toLowerCase()
                    })] = obj[key];
                    // 将之前大写的键属性删除
                    delete obj[key];
                }
                // 如果属性是对象或者数组,重新执行函数
                if (typeof temp === 'object' || Object.prototype.toString.call(temp) === '[object Array]') {
                    keysLower(temp);
                }
            }
        }
        return obj;
    };

    数组对象数据格式根据年龄排序

    var arr = [{'name': '张三', age: 26},{'name': '李四', age: 12},{'name': '王五', age: 37},{'name': '赵六', age: 4}];
    arr.sort( (a,b)=> b.age-a.age);
    console.log(arr)

    Object键值对去重

    function distinct(array) {
       var obj = {};
       return array.filter(function(item, index, array){
         return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
       })
    }

    数组对象数据格式查找指定属性值

    let json = [
                    {"CostTime": "310", "FromStation": "上海"},
                    {"CostTime": "336", "FromStation": "北京"},
                    {"CostTime": "310", "FromStation": "上海"},
                    {"CostTime": "336", "FromStation": "北京"},
                    {"CostTime": "310", "FromStation": "上海"},
                    {"CostTime": "336", "FromStation": "北京"},
                    {"CostTime": "310", "FromStation": "上海"},
                    {"CostTime": "336", "FromStation": "北京"},
                    {"CostTime": "310", "FromStation": "上海"},
                    {"CostTime": "310", "FromStation": "上海"},
                    {"CostTime": "336", "FromStation": "北京"}
                ]
     let filterMethod = (value) => value.CostTime == "310"  //查找CostTime 中值为310的对象
     let finallyData = json.filter(filterMethod); console.log(finallyData); 

    指定元素在数组中出现的位置

    var positionIndex = [];
    var arr = [1,5,6,1,7,8,1,6,6,6];
    var pos = arr.indexOf(1);
    while(pos!=-1){
       positionIndex.push(pos);
       pos = arr.indexOf(1,pos+1);
    }
    console.log(positionIndex); // => [0,3,6]

    获取url指定name的query参数

     function  getQueryName(name) {
            var query = window.location.search.substring(1);
            var vars = query.split("&");
            for (var i=0;i<vars.length;i++) {
                    var pair = vars[i].split("=");
                    if(pair[0] == name){return pair[1];}
            }
            return false;
        }

    获取url指定所有query参数

    function urlToObj(str){
            var obj = {};
            var arr1 = str.split("?");
          var arr2 = arr1[1].split("&");
          for(var i=0 ; i < arr2.length; i++){
            var res = arr2[i].split("=");
            obj[res[0]] = res[1];
          }
            return obj;
        }

    将obj转为url字符串

    var queryString = Object.keys(obj).map(key => key + '=' + obj[key]).join('&');

     ...

    读取cookie

    function getCookie(name){
            // 读取cookie
            let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
            arr = document.cookie.match(reg);
            if (arr){
                return unescape(arr[2]);  //unescape() 函数可对通过 escape() 编码的字符串进行解码。
            }else{
                return null;
            }
        }

    清除数组中的[false, null, 0, NaN, undefined, ""]

    let arr="123,456,4789,'   ','发送到发送',,,false,".split(',')
    arr.map(Number)  //转换为[123, 456, 4789, NaN, NaN, 0, 0, NaN, 0]

    [123, 456, 4789, NaN, NaN, 0, 0, NaN, 0].filter(val=>!(!val || val== ''));//清除数组中的[false, null, 0, NaN, undefined, ""]

    //组合起来 let arr2
    = arr.map(Number).filter(val=>!(!val || val== '')); //清除数组中的[false, null, 0, NaN, undefined, ""]

    算法基础:展平数组 

    1.使用 拓展运算符 ...

    let arr = [1,[2,3],[4,5]];
    let arr2 = ''    ;
    arr2=[].concat(...arr)
    console.log(arr2)

    缺点:只能展平两层  

    2.递归算法

    let arr=[1,[2,3],[[[4,5]]]];
    flatten(arr);
    function flatten(arr){
        return [].concat(
            ...arr.map(x => Array.isArray(x)?flatten(x):x)        
        )
    }
    console.log(flatten(arr))

    3.flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

    let arr3=[1,[2,3],[[[4,5]]]];   
    arr4=arr3.flat(Infinity)  //使用 Infinity 作为深度,展开任意深度的嵌套数组 

    算法基础:节流算法   

    目的:  距离上次执行超过60毫秒,才能执行

    代码: 

    function throttle(func,delay=60){
        let lock = false;
        return (...args) =>{
            if(lock){return}
                func(...args);
                lock = true;
                setTimeout( () =>{lock = false}, delay)    
        }
    }

    思路:执行throttle后 ,lock就是一把锁,只有当lock为false时才执行func,这把锁需要throttle距离上次执行相隔60毫秒才能为false

    算法基础:防抖算法  

    目的: 结束操作后的一定时间内才会执行

    function throttle(func,delay=300,i=null){
        return (...args) => {
            clearInterval(i);                 
            i=setTimeout(func.bind(null,...args),delay);
            //i=setTimeout((...args) =>func(...args),delay);// 同上一行代码效果一样
          }
    }

    思路:不停的操作,定时器就一直重复叠加执行,定时器 i 也就每次在被重复,需要每次执行throttle时将上一次的定时器i清除,并没有执行 func .结束操作后, 在清除上一次定时器后 再次设置定时器,执行func

    计算年月日

         const formatDuration = ms => {
              if (ms < 0) ms = -ms;
              const time = {
                day: Math.floor(ms / 86400000),
                hour: Math.floor(ms / 3600000) % 24 - 8, //修正东八区北京时间
                minute: Math.floor(ms / 60000) % 60,
                second: Math.floor(ms / 1000) % 60,
                millisecond: Math.floor(ms) % 1000
              };
              return Object.entries(time)
                .filter(val => val[1] !== 0)
                .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
                .join(', ');
            };
    
            // 事例
            formatDuration(1001); // '1 second, 1 millisecond'
            formatDuration(34325055574); 
            // '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds'
            var newdate = new Date().getTime()-  Date.UTC(2020,6,15,17,30)  //计算 当前时间距离与某一天的毫秒差
             console.log(formatDuration(newdate)) 

    jq获取指定元素的下标

    $('.nav').find('li').on('click', function () {
            let i = $('.nav li').index(this);
            console.log(i)
        })

    树结构遍历

        let tree = [{
                id: '1',
                title: '节点1',
                children: [{
                        id: '1-1',
                        title: '节点1-1'
                    },
                    {
                        id: '1-2',
                        title: '节点1-2',
                        children: [{
                            id: '1-2-1',
                            title: '节点1-2-1',
                        }]
                    }
                ]
            }, {
                id: '2',
                title: '节点2',
                children: [{
                        id: '2-1',
                        title: '节点2-1'
                    },
                    {
                        id: '2-2',
                        title: '节点2-2'
                    }
                ]
            }]


    //广度优先 function treeForeach(tree, func) { let node, list = [...tree] while (node = list.shift()) { func(node) node.children && list.push(...node.children) } }
        
         treeForeach(tree, node => {
                console.log(node.title)
            })  
    
    
            //节点1
            //节点2
            //节点1-1
            //节点1-2
            //节点2-1
            //节点2-2
            //节点1-2-1
    
    
           //深度优先
            function treeForeach2(tree, func) { //先序遍历
                tree.forEach(data => {
                    func(data)
                    data.children && treeForeach2(data.children, func) //遍历子树
                })
            }
            treeForeach2(tree, node => {
                console.log(node.title)
            })
        
            //节点1
            // 节点1-1
            // 节点1-2
            // 节点1-2-1
            // 节点2
            // 节点2-1
            // 节点2-2
    
    

    列表和树结构相互转换

            let list = [{
                id: '1',
                title: '节点1',
                parentId: ''
            }, {
                id: '1-1',
                title: '节点1-1',
                parentId: '1'
            }, {
                id: '1-2',
                title: '节点1-2',
                parentId: '1'
            }, {
                id: '2',
                title: '节点2',
                parentId: ''
            }, {
                id: '2-1',
                title: '节点2-1',
                parentId: '2'
            }, ]
    
            console.log('------------------树结构转列表结构-----递归')
    
            function treeToList(tree, result = [], level = 0) {
                tree.forEach(node => {
                    result.push(node)
                    node.level = level + 1;
                    node.children && treeToList(node.children, result, level + 1)
                })
                return result;
            }
          //result 容器 ; level 记录层级 console.log(treeToList(tree)); console.log(
    '------------------树结构转列表结构-----循环') function treeToList2(tree) { let node, result = tree.map(node => (node.level = 1, node)) for (let i = 0; i < result.length; i++) { if (!result[i].children) continue; let list = result[i].children.map(node => (node.level = result[i].level + 1, node)) result.splice(i + 1, 0, ...list) } return result } console.log(treeToList2(tree)); console.log('------------------列表结构转树结构-----') function listTotree(list) { let info = list.reduce((map, node) => (map[node.id] = node, node.children = [], map), {}) return list.filter(node => { info[node.parentId] && info[node.parentId].children.push(node) return !node.parentId }) } console.log(listTotree(list));

    查找节点路径

     console.log('------------------查找节点路径-----')
            //方法一
            function treeFindPath(tree, func, path = []) {
                if (!tree) return []
                for (const data of tree) {
                    path.push(data.id)
                    if (func(data)) return path
                    if (data.children) {
                        const findChildren = treeFindPath(data.children, func, path)
                        if (findChildren.length) return findChildren
                    }
                    path.pop()
                }
                return []
            }
    
    
    
            //方法二
            function treeFindPath(tree, func, path = [], result = []) {
                for (const data of tree) {
                    path.push(data.id)
                    func(data) && result.push([...path])
                    data.children && treeFindPath(data.children, func, path, result)
                    path.pop()
                }
                return result
            }
            let result = treeFindPath(tree, node => node.id === '1-2-1')
            console.log(result)

    ..

  • 相关阅读:
    停下来,等等灵魂(二)
    停下来,等等灵魂(一)
    swoole流程图
    使用 Spring Cloud Sleuth、Elastic Stack 和 Zipkin 做微服务监控
    Portainer实战
    Docker 容器日志分析
    docker容器日志查看
    java(集合框架)(转)
    js中const,var,let区别与用法(转)
    【MySQL】Mac通过brew安装的MySQL重启方法
  • 原文地址:https://www.cnblogs.com/wxyblog/p/12462574.html
Copyright © 2011-2022 走看看