IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    JavaScript算法练习:从数组中寻找元素并删除元素

    Airen发表于 2016-06-01 12:45:21
    love 0

    今天的任务中创建一个destroyer()函数,其功能是对所给的数组根据参数删除这些元素。也就是说给destroyer()传入一个参数arr,而且这个参数是类似这样的[1,2,3,4,5,2,3,1,3],1,3,要做的事情就是从数组[1,2,3,4,5,2,3,1,3]删除所有的1和3元素。

    实现思路

    知道要完成的任务之后,要有一个实现思路,其简单的可以概括为:

    • 通过arguments对象将所有参数包装成一个数组args
    • 通过JavaScript的一些方法将arr参数移除,也就是需要删除的参数
    • 通过Array.indexOf()将arr除外的args数组做为过滤的条件
    • 通过filter()方法创建过滤条件,将arr中符合filter()条件的元素删除,当然除了通过filter()之外,还可以使用JavaScript中的for循环
    • 返回最后的arr

    将涉及到的JavaScript方法

    有思路了,就好办了,这里简单罗列一些将要用到的JavaScript方法:

    • arguments
    • Array.prototype.indexOf()
    • Array.prototype.filter()

    上面的知识点是后面所有解决方案都将会涉及到的。为了更好的理解后面的解决方案,简单的回忆一下这几个知识点。

    arguments是一个类数组对象。代表传给一个function的参数列表。它是函数内部的本地变量,已不再是函数的属必了。可以在函数内部通过使用arguments对象来获取函数的所有参数。

    特别强调了,arguments对象仅在函数内部有效,在函数外部调用arguments对象会出现一个错误。来看一个简单的示列:

    function destroyer (arr) {
        // 将所传的参数转换成数组args
        var args = arguments;
        console.log(args); //[[1,2,1,3,2,1,3,4,2,6],1,2]
    
        for (var i = 0, len = arguments.length; i < len; i++) {
            console.log(arguments[i]);
            /*
             * i = 0 => arguments[0] = [1,2,1,3,2,1,3,4,2,6]
             * i = 1 => arguments[1] = 1
             * i = 2 => arguments[2] = 2
             */
        }
    }
    
    destroyer([1,2,1,3,2,1,3,4,2,6],1,2);
    

    从上面的示例,可以知道,通过arguments[0]可以获取到的数组arr,也就是目标数组。同时通过JavaScript的push()、splice()或者shift()之类的方法来删除args数组中的第一个元素,从而得到需要从arr中移除的参数,其也是一个数组,比如说将其称为removeArgs。

    其实除了这些方法之外,可以通过arguments带一个参数,就可以直接得到需要移除的参数removeArgs数组:

    removeArgs = Array.prototype.slice.call(arguments, 1); // [1, 2]
    

    这样一来,就得到了目标数组,比如说将其称之为newArray和需要移除的数组removeArgs。那么就可以Array.prototype.indexOf()获取removeArgs中的索引值index,如果其等于-1,就表示元素不在数组removeArgs中,否则将返回对应的索引值:

    [1,2].indexOf(1) = 0 
    

    然后使用===或者!==来做比较

    removeArgs.indexOf(value) === -1;
    

    如果其值不为-1将返回false。

    [1,2].indexOf(1) = 0  => false
    [1,2].indexOf(2) = 1  => false
    

    而我们的目标就是从newArray中移除removeArgs中有相同的元素。比如说:

    newArray = [1,2,1,3,2,1,3,4,2,6]
    removeArgs= [1,2]
    

    也就是说从[1,2,1,3,2,1,3,4,2,6]移除所有的1和2,最后得到的数组arr:

    arr = [3, 3, 4, 6]
    

    要从一个数组中过滤掉对应的参数,大家肯定会想到filter()方法,如果其callback函数返回的值为false时,就会从数组中删除这个值,从而将符合条件的元素组成一个新的数组。也就是我们最终需要的数组arr。

    解决方案

    要实现这个功能,实现方案非常的多,下面罗列一些搜集来的解决方案,以供大家学习和参考:

    方法1

    function destroyer(arr) {
        // 获取目标数组
        var newArray = arguments[0]; // [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
        // 声明一个空数组,用来存储需要从`newArray`中删除的元素
        var removeArgs = [];
    
        for (var i = 1, len = arguments.length; i < len; i++) {
            removeArgs.push(arguments[i]);
            /*
             *  遍历次数  i  len   i < len  i++  arguments[i]  removeArgs
             *  1st     1    3     yes      2     1            [1]
             *  2nd     2    3     yes      3     2            [1,2]
             *  3rd     3    3     no
             *  end loop
             *  
             */
        }
    
        // 声明filter()方法的callback函数
    
        function isFalse (value) {
            return removeArgs.indexOf(value) === -1;
    
            /*
             *  removeArgs = [1,2]
             *  removeArgs.indexOf(value) = ?  removeArgs.indexOf(value) === -1
             *  [1,2].indexOf(1) = 0              false
             *  [1,2].indexOf(2) = 1              false
             *
             */
        }
    
        return newArray.filter(isFalse);// newArray中删除1,2
    }
    

    在Chrome中运行后:

    destroyer([1,2,1,3,2,1,3,4,2,6],1,2); // [3, 3, 4, 6]
    

    方法2

    function destroyer(arr) {
        var newArray = arguments[0]; //[1,2,1,3,2,1,3,4,2,6]
        var removeArgs = [];
    
        for (var i = 1, len = arguments.length; i < len; i++) {
            removeArgs.push(arguments[i]);
            /*
             *  遍历次数  i  len   i < len  i++  arguments[i]  removeArgs
             *  1st     1    3     yes      2     1            [1]
             *  2nd     2    3     yes      3     2            [1,2]
             *  3rd     3    3     no
             *  end loop
             *  
             */
        }
    
        function isFalse (value) {
          for (var j = 0; j < removeArgs.length; j++) {
            if (removeArgs[j] == value) {
              return false;
            }
            /*
             * removeArgs = [1,2]
             * 遍历次数   j = ?  j < removeArgs.length  j++  removeArgs[j]   value  removeArgs[j] == value
             * 1st        0     yes                    1     1               1       false
             * 2nd        1     yes                    2     2               2       false
             * 3rd        2     no
             * end loop
             * 
             */
          }
          return true;
        }
    
        return newArray.filter(isFalse); // 从newArray数组中删除1,2
    }
    

    方法3

    function destroyer(arr) {
        var args = Array.prototype.slice.call(arguments); // [[1,2,1,3,2,1,3,4,2,6],1,2]
        args.splice(0, 1); // 从数组中args删除第一个元素[1,2,1,3,2,1,3,4,2,6], args数组变成[1,2]
    
        // arr = [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
        return arr.filter(function(value) {
            return args.indexOf(value) === -1;
        });
    }
    

    方法4

    function destroyer(arr) {
        var removeArgs = Array.prototype.slice.call(arguments, 1); // [1, 2]
    
        // arr = [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
        return arr.filter(function(value) {
            return removeArgs.indexOf(value) < 0;
        });
    }
    

    方法5

    function destroyer(arr) {
        var args = arguments;//[[1, 2, 1, 3, 2, 1, 3, 4, 2, 6], 1, 2]
    
        function isFalse (value) {
          for (var i = 1, len = args.length; i < len; i++){
            if (args[i] == value) {
              return false;
            }
          }
          return true;
        }
        // arr = [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
        return arr.filter(isFalse);
    }
    

    方法6

    function destroyer(arr) {
        var args = Array.prototype.slice.call(arguments); //[[1, 2, 1, 3, 2, 1, 3, 4, 2, 6], 1, 2]
        var newArray = args.shift(); //[1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
        // 这里args = [1,2]
    
        function isFalse (a) {
          return args.every( function (b) {
            return a !== b;
          });
        }
    
        return newArray.filter(isFalse);
    }
    

    方法7

    function destroyer(arr) {
        var removeArgs = Array.prototype.slice.call(arguments, 1);// [1,2]
    
        function isFalse (a) {
          return !removeArgs.some (function (b) {
            return a === b;
          })
        }
    
        return arr.filter(isFalse);
    }
    

    方法8

    function destroyer(arr) {
        var removeArgs = Array.prototype.slice.call(arguments, 1); // [1,2]
        removeArgs.forEach(function(value) {
            // arr = [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
            var index = arr.indexOf(value);
            while (index > -1) {
                arr.splice(index, 1);
                index = arr.indexOf(value);
            }
        });
        return arr;
    }
    

    方法9

    function destroyer(arr) {
        // arguments = [[1, 2, 1, 3, 2, 1, 3, 4, 2, 6],1,2]
        for (var i = 1; i < arguments.length; i++) {
            // arr = [1, 2, 1, 3, 2, 1, 3, 4, 2, 6]
            for (var j = 0; j < arr.length; j++) {
                if (arguments[i] == arr[j]) {
                    arr.splice(j, 1);
                    --j;
                }
            }
        }
        return arr;
    }
    

    也可以换成这样的方式:

    function destroyer(arr) {
        for (var i = 1; i < arguments.length; i++) {
            for (var j = arr.length - 1; j >= 0; j--) {
                if (arguments[i] == arr[j]) {
                    arr.splice(j, 1);
                }
            }
        }
        return arr;
    }
    

    方法10

    除了上述方法之外,还可以使用ES6中的一些方法:

    • new Set()
    • has()

    比如:

    function destroyer(arr) {
        var removeArgs = new Set(Array.prototype.slice.call(arguments, 1)); //Set {1, 2}
    
        function isFalse (value) {
          return !removeArgs.has(value);
        }
    
        return arr.filter(isFalse);
    }
    

    也可以将上述方法改成:

    function destroyer(arr, ...items) {
        var removeArgs = new Set(items); // Set {1, 2}
    
        function isFalse (value) {
            return !removeArgs.has(value);
        }
    
        return arr.filter(isFalse);
    }
    

    总结

    上面使用了十种方法实现了我们要完成的任务。不管什么使用什么方法,都有自己的优势和弊端。我想说的是,只要大家掌握了基础,对这JavaScript这些基础知识了解通透,我们就可以从不同的角度和使用不同的方法达到我们的目标,或者完成我们所要完成的任务。当然如果你经验十足,您能找到最简单,最高效的方案。如果您有更好的解决方案,欢迎在下面的评论中与我们分享。最后再给大家提供一个视频:

    大漠

    常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

    如需转载,烦请注明出处:http://www.w3cplus.com/javascript/seek-and-destroy-in-javascript.html

    JavaScript
    javaScript
    JavaScript学习笔记
    JavaScript算法练习


沪ICP备19023445号-2号
友情链接