前端常用算法集合,持续更新...

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;
    }

方法二

function getQueryString(name) {
    var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
    var r = window.location.search.substr(1).match(reg)
    if (r !== null) return unescape(r[2])
    return null
  }

 

获取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;
    }

方法二

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj(url) {
  const search = url.split('?')[1]
  if (!search) {
    return {}
  }
  return JSON.parse(
    '{"' +
      decodeURIComponent(search)
        .replace(/"/g, '\\"')
        .replace(/&/g, '","')
        .replace(/=/g, '":"')
        .replace(/\+/g, ' ') +
      '"}'
  )
}

 

将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, ""]

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

function filterParams(obj) {
  const keys = Object.keys(obj)
  keys.forEach(key => {
    const value = obj[key]
    if (isObject(value)) filterParams(value)
    if (isEmpty(value)) delete obj[key]
  })
  return obj
}

function isEmpty(input) {
  return [  , undefined, null].includes(input)
}

function isObject(input) {
  return input !== null && (!Array.isArray(input)) && typeof input ===  object 
}

this.storeArr

将 this.storeArr 数组对象中key值为position_ename , value相同的对象归类为一个数组并添加到this.newData对象中 
key值为this.storeArr中 position_ename的value
this.storeArr.forEach(e => {
    if (Object.keys(this.newData).indexOf('' + e.position_ename) === -1) {
          this.$set(this.newData,e.position_ename,[])
    }
     this.newData[e.position_ename].push(e)          
})

 

算法基础:展平数组 

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)
//方法三
findPath(root, targetId) {
if (!root) return null;
let queue = [{ node: root, path: [] }];
while (queue.length > 0) {
let { node, path } = queue.shift();
path.push(node);
if (node.id === targetId) {
return path;
}
for (let child of node.children) {
queue.push({ node: child, path: [...path] });
}
}
return null;
},

 

posted @ 2020-03-11 15:15  混名汪小星  阅读(626)  评论(0编辑  收藏  举报