JavaScript中Array算法

Array类型

判断一个变量时数组还是对象

typeof运算符在判断基本数据类型时会很有用,但是在判断引用数据类型时,却显得很吃力。

  • instanceof运算符
        function getDataType(o) {
            if (o instanceof Array) {
                return 'Array';
            } else if (o instanceof Object) {
                return 'Object';
            } else {
                return 'param is not object type';
            }
        }
        var a = [1, 2, 3];
        console.log(getDataType(a));
  • 判断构造函数
        //判断变量是数组还是对象
        function getDataType(o) {
            //获取构造函数
            var constructor = o.__proto__.constructor || o.constructor;
            if (constructor === Array) {
                return 'Array';
            } else if (constructor === Object) {
                return 'Object';
            } else {
                return 'param is not object type';
            }
        }
        var a = [1, 2, 3];
        console.log(getDataType(a));
  • toString函数
    借助call()函数,直接调用Object原型上的toString()函数
        //判断变量是数组还是对象
        function getDataType(o) {
            var result = Object.prototype.toString.call(o);
            if (result === '[object Array]') {
                return 'Array';
            } else if (result === '[object Object]') {
                return 'Object';
            } else {
                return 'param is no object type';
            }
        }
        var a = [1, 2, 3];
        console.log(getDataType(a));
  • Array.isArray()函数
    数组增加一个isArray()静态函数,用于判断变量是否为数组。该函数只能判断变量是否为数组,并不能确定是否为对象
        console.log(Array.isArray([]));
        console.log(Array.isArray(null));

在这里插入图片描述

filter()函数过滤满足条件的数据

filter()函数用于过滤出满足条件的数据,返回一个新的数组,不会改变原来的数组。
filter()函数接收一个函数作为其参数,返回值为"true"的元素会被添加至新的数组中,返回值为"false"的元素则不会被添加至新的数组中,最后返回这个新的数组。

  • 针对简单类型的数组,找出数组中所有为奇数的数字
        var filterFn = function (x) {
            return x % 2;
        };
        var arr = [1, 2, 3, 4, 5, 6, 7, 9, 15, 16];
        var result = arr.filter(filterFn);
        console.log(result);

在这里插入图片描述

  • 针对复杂类型的数组,找出所有年龄大于18岁的男生
        var arrObj = [{
            gender: '男',
            age: 20
        },
        {
            gender: '女',
            age: 23
        },
        {
            gender: '女',
            age: 20
        },
        {
            gender: '男',
            age: 17
        }];
        var filterFn = function (obj) {
            return obj.age > 18 && obj.gender === '男';
        };
        var result = arrObj.filter(filterFn);
        console.log(result);

在这里插入图片描述

reduce()函数累加器处理数组元素

reduce()函数最主要的作用是接收一个函数作为累加器,将数组中的每一个元素从左至右依次执行累加器,返回最终的处理结果

  • 求数组每个元素相加的和
        var arr = [1, 2, 3, 4, 5];
        var sum = arr.reduce(function (accumulator, currentValue) {
            return accumulator + currentValue;
        }, 0);
        console.log(sum);
  • 统计数组中每个元素出现的次数
        var countOccurrences = function (arr) {
            return arr.reduce(function (accumulator, currentValue) {
                accumulator[currentValue] ? accumulator[currentValue]++ : accumulator[currentValue] = 1;
                return accumulator;
            }, {});
        };
        console.log(countOccurrences([1, 3, 2, 2, 5, 1]));
  • 多维度统计数据
    将一组人民币分别换算成美元和欧元的等量值
        //首先我们需要一组人民币值
        var items = [{ price: 10 },
        { price: 50 },
        { price: 100 }];
        //利用reduce()函数单独完成一个汇率的计算
        var reducers = {
            totallnEuros: function (state, item) {
                return state.euros += item.price * 0.1265;
            },
            totallnDollars: function (state, item) {
                return state.dollars += item.price * 0.1487;
            }
        };
        //上面的reducers通过一个manager()函数,利用object.keys()函数同时执行多个函数,每个函数完成各自的汇率计算
        var manageReducers = function (reducers) {
            return function (state, item) {
                return Object.keys(reducers).reduce(
                    function (nextState, key) {
                        reducers[key](state, item);
                        return state;
                    },
                    {}
                );
            }
        };
        //对上面的一组人民币值Items数组进行运算
        var bigTotalPriceReducer = manageReducers(reducers);
        var initialState = { euros: 0, dollars: 0 };
        var totals = items.reduce(bigTotalPriceReducer, initialState);
        console.log(totals);

求数组的最大值和最小值

  • 通过prototype属性扩展min()函数和max()函数
        Array.prototype.min = function () {
            var min = this[0];
            var len = this.length;
            for (var i = 1; i < len; i++) {
                if (this[i] < min) {
                    min = this[i];
                }
            }
            return min;
        };
        Array.prototype.max = function () {
            var max = this[0];
            var len = this.length;
            for (var i = 1; i < len; i++) {
                if (this[i] > max) {
                    max = this[i];
                }
            }
            return max;
        };
        var arr = [2, 56, 34, 1, 89, 99];
        console.log(arr.max());
        console.log(arr.min());
  • 借助Math对象的min()函数和max()函数
    通过apply()函数改变函数的执行体,将数组作为参数传递给apply()函数,这样数组就可以直接调用Math()对象的min()函数和max()函数来获取返回值
        //最大值
        Array.max = function (array) {
            return Math.max.apply(Math, array);
        };
        //最小值
        Array.min = function (array) {
            return Math.min.apply(Math, array);
        };
        var arr = [2, 56, 34, 1, 89, 99];
        console.log(Array.max(arr));
        console.log(Array.min(arr));
    </script>
  • 算法2的优化(实际运用中推荐)
    将算法2中的静态函数优化为支持链式调用
        Array.prototype.max = function () {
            return Math.max.apply({}, this);
        };
        Array.prototype.min = function () {
            return Math.min.apply({}, this);
        };
        //max和Min函数属于实例方法。可以直接通过数组调用
        var arr = [2, 56, 34, 1, 89, 99];
        console.log(arr.max());
        console.log(arr.min());
  • 借助Array类型的reduce()函数
        //最大值
        Array.prototype.max = function () {
            return this.reduce(function (preValue, curValue) {
                return preValue > curValue ? preValue : curValue;
            });
        };
        //最小值
        Array.prototype.min = function () {
            return this.reduce(function (preValue, curValue) {
                return preValue > curValue ? curValue : preValue;
            });
        };
        var arr = [2, 56, 34, 1, 89, 99];
        console.log(arr.max());
        console.log(arr.min());
  • 借助Array类型的sort()函数
    借助数组原生的sort()函数对数组进行排序,排序完成后的首尾元素即是数组的最小、最大元素
        var sortFn = function (a, b) {
            return a - b;
        };
        var arr = [2, 56, 34, 1, 89, 99];
        var sortArr = arr.sort(sortFn);
        console.log(sortArr[0]);
        console.log(sortArr[sortArr.length - 1]);
  • 借助ES6的扩展运算符
        var arr = [2, 56, 34, 1, 89, 99];
        console.log(Math.min(...arr));
        console.log(Math.max(...arr));

数组遍历的7种方法

  • 最原始的for循环
        var arr = [2, 56, 34, 1, 89, 99];
        for (var i = 0; i < arr.length; i++) {
            console.log(arr[i]);
        }
  • 基于forEach()函数的方法
    forEach()函数算是在数组实例方法中用于遍历调用次数最多的函数
        var arr = [11, 22, 33];
        arr.forEach(function (element, index, array) {
            console.log(element);
        })

forEach()函数是在ES5中新添加的,它可能不兼容只支持低版本js的浏览器,供一个polyfill来实现(代码参考书籍)

  • 基于map()函数的方法
    map()函数并不会改变原数组,其接收的参数和forEach()函数一样
    map()回调函数中需要通过return返回处理后的值
    将一个数组中的每个元素做平方运算,通过map()函数很容易做到
        var arr = [1, 2, 3];
        var arrayOfSquares = arr.map(function (element) {
            return element * element;
        });
        console.log(arrayOfSquares);
  • 基于some()函数与every()函数的方法
        function isBigEnough(element, index, array) {
            return element > 4;
        }
        var passed1 = [1, 2, 3, 4].some(isBigEnough);
        var passed2 = [1, 2, 3, 4, 5].some(isBigEnough);
        console.log(passed1);
        console.log(passed2);
        var passed3 = [2, 3, 4].every(isBigEnough);
        var passed4 = [5, 6].every(isBigEnough);
        console.log(passed3);
        console.log(passed4);
  • 基于find()函数的方法
        var value = [1, 5, 10, 15].find(function (element, index, array) {
            return element > 9;
        });
        var value2 = [1, 5, 10, 15].find(function (element, index, array) {
            return element > 20;
        });
        console.log(value);
        console.log(value2);

在这里插入图片描述

数组去重的7种算法

  • 遍历数组
    在函数内部新建一个数组,对传入的数组进行遍历。如果遍历的值不在新数组种就添加进去,如果已存在就不做处理
        function arrayUnique(array) {
            var result = [];
            for (var i = 0; i < array.length; i++) {
                if (result.indexOf(array[i]) === -1) {
                    result.push(array[i]);
                }
            }
            return result;
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7];
        console.log(arrayUnique(array));
  • 利用对象键值对
    新建一个js对象以及一个新的数组,对传入的数组进行遍历,判断当前遍历的值是否为js对象的键。如果是,表示该元素已经出现过,不做处理;如果不是,表示第一次出现,给该js对象插入该键,同时插入新的数组
        function arrayUnique1(array) {
            var obj = {},
                result = [],
                val, type;
            for (var i = 0; i < array.length; i++) {
                val = array[i];
                if (!obj[val]) {
                    obj[val] = 'yes';
                    result.push(val);
                }
            }
            return result;
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7];
        console.log(arrayUnique1(array));

上面的代码存在缺陷,即不能判断Number类型和String类型的数字

        function arrayUnique1(array) {
            var obj = {},
                result = [],
                val, type;
            for (var i = 0; i < array.length; i++) {
                val = array[i];
                type = typeof val;
                if (!obj[val]) {
                    obj[val] = [type];
                    result.push(val);
                } else if (obj[val].indexOf(type) < 0) {
                    //判断数据类型是否存在
                    obj[val].push(type);
                    result.push(val);
                }
            }
            return result;
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
        console.log(arrayUnique1(array));
  • 先排序,再去重
    先用sort()函数对数组进行排序,然后对排序后的数组进行相邻元素的去重,将去重的后的元素添加至新的数组中
        function arrayUnique3(array) {
            var result = [array[0]];
            array.sort(function (a, b) {
                return a - b;
            });
            for (var i = 0; i < array.length; i++) {
                if (array[i] !== result[result.length - 1]) {
                    result.push(array[i]);
                }
            }
            return result;
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
        console.log(arrayUnique3(array));
  • 优先遍历数组
    利用双层循环

  • 基于reduce()函数
    利用reduce()函数,借助一个key-value对象

        function arrayUnique5(array) {
            var obj = {}, type;
            return array.reduce(function (preValue, curValue) {
                type = typeof curValue;
                if (!obj[curValue]) {
                    obj[curValue] = [type];
                    preValue.push(curValue);
                } else if (obj[curValue].indexOf(type) < 0) {
                    obj[curValue].push(type);
                    preValue.push(curValue);
                }
                return preValue;
            }, []);
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
        console.log(arrayUnique5(array));
  • 借助ES6的Set数据结构
    Set数据结构,类似于数组,有一个特点,即成员都是唯一的,所以Set具有自动去重的功能
    在ES6中,Array类型增加了一个from()函数,用于将类数组对象转化为数组,然后再结合Set可以完美实现数组的去重
        function arrayUnique6(array) {
            return Array.from(new Set(array));
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
        console.log(arrayUnique6(array));
  • 借助ES6的Map数据结构
    基于key-value存储数据的结构。每个key都只对应唯一的value
    基于Map数据结构,通过filter()函数过滤,即可获得去重后的结果
        function arrayUnique7(array) {
            var map = new Map();
            return array.filter((item) => !map.has(item) && map.set(item, 1));

        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7, '1'];
        console.log(arrayUnique7(array));

找出数组中出现次数最多的元素

  • 利用键值对
    将数组元素作为对象的键,出现的次数作为值
    获取键值对后进行遍历,获取值最大的那个元素
        function findMost1(arr) {
            if (!arr.length) {
                return;
            }
            if (arr.length === 1) {
                return 1;
            }
            var res = {};
            //遍历数组
            for (var i = 0; i < arr.length; i++) {
                if (!res[arr[i]]) {
                    res[arr[i]] = 1;
                } else {
                    res[arr[i]]++;
                }
            }
            //遍历res
            var keys = Object.keys(res);
            var maxNum = 0, maxEle;
            for (var i = 0; i < arr.length; i++) {
                if (res[keys[i]] > maxNum) {
                    maxNum = res[keys[i]];
                    maxEle = arr[i];
                }
            }
            return maxEle + ":" + maxNum;
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7, 7, 7];
        console.log(findMost1(array));  

object.key()返回的是res键值对里面的键

  • 对算法1的优化
    将两次遍历优化为一次遍历
        function findMost2(arr) {
            var h = {};
            var maxNum = 0;
            var maxEle = null;
            for (var i = 0; i < arr.length; i++) {
                var a = arr[i];
                h[a] === undefined ? h[a] = 1 : h[a]++;
                //在当前循环中直接比较出现次数最大值
                if (h[a] > maxNum) {
                    maxEle = a;
                    maxNum = h[a];
                }
            }
            return maxEle + ":" + maxNum;
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7, 7, 7];
        console.log(findMost2(array));   
  • 借助Array类型的reduce()函数
        function findMost3(arr) {
            var maxEle;
            var maxNum = 1;
            var obj = arr.reduce(function (p, k) {
                p[k] ? p[k]++ : p[k] = 1;
                if (p[k] > maxNum) {
                    maxEle = k;
                    maxNum++;
                }
                return p;
            }, {});
            return maxEle + ":" + maxNum;
        }
        var array = [1, 4, 4, 6, 7, 5, 4, 7, 7, 7];
        console.log(findMost3(array)); 
  • 借助ES6与逗号运算符进行代码优化(暂不理解)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值