【问题标题】:Clean way to remove element from javascript array (with jQuery, coffeescript)从 javascript 数组中删除元素的干净方法(使用 jQuery、coffeescript)
【发布时间】:2011-06-17 02:00:49
【问题描述】:

对此有很多问题,尤其是: jQuery version of array containsa solution with the splice method 等等。然而,它们看起来都很复杂和烦人。

结合 javascript、jQuery 和 coffeescript 的强大功能,从 javascript 数组中删除元素的最简洁的方法是什么?我们事先并不知道指数。在代码中:

a = [4,8,2,3]
a.remove(8)     # a is now [4,2,3]

如果没有一个好的内置方法,那么扩展 javascript 数组以支持这种方法的干净方法是什么?如果有帮助,我真的在使用数组作为集合。理想情况下,解决方案将在具有 jQuery 支持的咖啡脚本中很好地工作。另外,我不在乎速度,而是优先考虑清晰、简单的代码。

【问题讨论】:

    标签: javascript jquery coffeescript


    【解决方案1】:

    CoffeeScript:

    Array::remove = (e) -> @[t..t] = [] if (t = @indexOf(e)) > -1
    

    这只是拼接出位置t处的元素,即找到e的索引(如果确实找到了t > -1)。 Coffeescript 将其翻译为:

    Array.prototype.remove = function(e) {
        var t, _ref;
        if ((t = this.indexOf(e)) > -1) {
            return ([].splice.apply(this, [t, t - t + 1].concat(_ref = [])), _ref);
        }
    };
    

    如果你想删除所有匹配的元素,并返回一个新数组,使用 CoffeeScript 和 jQuery:

    Array::remove = (v) -> $.grep @,(e)->e!=v
    

    翻译成:

    Array.prototype.remove = function(v) {
        return $.grep(this, function(e) {
            return e !== v;
        });
    };
    

    或者在没有 jQuery 的 grep 的情况下做同样的事情:

    Array::filterOutValue = (v) -> x for x in @ when x!=v
    

    翻译为:

    Array.prototype.filterOutValue = function(v) {
        var x, _i, _len, _results;
        _results = [];
        for (_i = 0, _len = this.length; _i < _len; _i++) {
            x = this[_i];
            if (x !== v) {
                _results.push(x);
            }
        }
        return _results;
    };
    

    【讨论】:

    • 显然您使用 CoffeeScript 的时间比我长得多; +1 看起来非常地道。
    • 感谢@Amir 提供了一个很棒的惯用答案。其他答案也很有帮助;我喜欢这个,因为它使用可用的工具使事情变得更简单。一个小改动:我可能会称它为 Array::removing,就像在 smaller_array = larger_array.removing(something) 中一样,所以很明显它返回了一个新数组。
    • 该死的咖啡脚本很漂亮。我相信你可以摆脱 @.indexOf 并只做 @indexOf (无点)。
    • 去掉不必要的concat:Array::remove = (v) -&gt; @splice i, 1 if i = @indexOf(v) &gt; -1
    • 感谢$.grep @,(e)-&gt;e!=v 我再也不会考虑使用 CoffeeScript。可读性为零。
    【解决方案2】:

    使用原生 Javascript:

    Array.prototype.remove = function(elem) {
        var match = -1;
    
        while( (match = this.indexOf(elem)) > -1 ) {
            this.splice(match, 1);
        }
    };
    
    var a = [4, 8, 2, 3];
    
    a.remove(8);
    

    只有 jQuery:

    jQuery.removeFromArray = function(value, arr) {
        return jQuery.grep(arr, function(elem, index) {
            return elem !== value;
        });
    };
    
    var a = [4, 8, 2, 3];
    
    a = jQuery.removeFromArray(8, a);
    

    【讨论】:

    • 虽然我当然应该进行基准测试,但我怀疑这会因为 indexOf 是 O(n) 而变慢,给你总复杂度 O(n * m + n) 对于 m 的数量火柴。我的答案只通过一次,复杂度为 O(n)。
    • @Domenic:当然。 .index() 没有那么快,但它足够公平并且代码更少。如果我追求性能,无论如何我都会使用while() 循环:请参阅jsperf.com/benchmark-for-domenic
    • 哈哈,你的 jsPerf 发现了 Chrome 和 Firefox 4b10 的区别,不错! for 版本在我的 Firefox 中的运行速度明显比在您的 Chrome 中运行得快得多。酷!
    • @Domenic:确实很奇怪。
    【解决方案3】:

    使用 jQuery 真的很容易:

    var index = $.inArray("value", myArray);
    if(index != -1)
    {
      myArray.splice(index, 1);
    }
    

    注意事项:

    splice 返回被移除的元素,所以不要使用myArray = myArray.splice()myArray.splice(index,1) 表示“从数组中删除索引'index' 处的数组元素”。

    $.inArray 返回您要查找的值在数组中的索引,如果该值不在数组中,则返回 -1。

    【讨论】:

    • 几乎和原生 JS 一样简单
    • 这似乎只删除了一个匹配的条目。一个数组可以包含多个具有相同值的条目。
    • 问题问:“从 javascript 数组中删除 an 元素的最干净的方法是什么?”
    【解决方案4】:

    这看起来很干净且易于理解;与其他答案不同,它考虑了一个元素出现多次的可能性。

    Array.prototype.remove = function (value) {
        for (var i = 0; i < this.length; ) {
            if (this[i] === value) {
                this.splice(i, 1);
            } else {
               ++i;
            }
        }
    }
    

    在 CoffeeScript 中:

    Array::remove = (value) ->
        i = 0
        while i < @length
            if @[i] == value
                @splice i, 1
            else
                ++i
        return @
    

    【讨论】:

      【解决方案5】:

      如果您还使用 CoffeeScript 创建者的 underscore.js 库,这里有一个可以很好地工作的单行:

      a = _(a).reject (v)-> v is e
      

      或在js中:

      a = _(a).reject(function(v) { return v == e; });
      

      【讨论】:

        【解决方案6】:

        虽然您要求使用 Coffeescript 或 jQuery 的简洁方法,但我发现最简洁的方法是使用 vanilla javascript 方法 filter:

        array.filter(function (item) { return item !== match });
        

        它在coffeescript 中看起来更干净,但它转换为完全相同的javascript,所以我只认为它是视觉上的差异,而不是coffeescript 的高级功能:

        array.filter (item) -> item isnt match
        

        旧版浏览器不支持过滤器,但 Mozilla 提供了符合 ECMA 标准的 polyfill。我认为这是一种非常安全的方法,因为您只是将旧浏览器引入现代标准,而不是在 polyfill 中发明任何新功能。

        很抱歉,如果您专门寻找仅 jQuery 或 Coffeescript 的方法,但我认为您主要要求的是库方法,因为您不知道纯 javascript 方法。

        你有它,不需要库!

        【讨论】:

        • 我喜欢这种方法和推理。
        【解决方案7】:

        这只是对Amir's awesome solution的轻微改动:

        Array::remove = (e) -> @splice(t,1)[0] if (t = @indexOf(e)) > -1
        

        如果列表中有元素,则返回元素,因此您可以执行以下操作:

        do_something 100 if a.remove(100)
        

        remove coffee 脚本翻译成这个 javascript:

        Array.prototype.remove = function(e) {
          var t, _ref;
          if ((t = this.indexOf(e)) > -1) {
            return ([].splice.apply(this, [t, t - t + 1].concat(_ref = [])), _ref);
          }};
        

        【讨论】:

          【解决方案8】:

          你可以试试 jQuery 的 grep 实用程序:

          a = [4,8,2,3]
          $.grep(a,function(v){return v!=8;})
          

          这里可能存在性能问题,因为您在技术上导致变量引用 new 数组;您并没有真正修改原始版本。假设原始文件没有在其他地方引用,垃圾收集器应该很快或者这个。这对我来说从来都不是问题,但其他人可能更清楚。干杯!

          【讨论】:

            猜你喜欢
            • 2020-02-09
            • 2018-04-07
            • 2018-04-11
            • 2012-03-14
            • 2020-11-02
            • 1970-01-01
            • 1970-01-01
            • 2022-12-26
            • 2018-08-13
            相关资源
            最近更新 更多