Чистый способ удалить элемент из массива javascript (с помощью jQuery, coffeescript)

Есть много вопросов по этому поводу, не в последнюю очередь: версия массива jQuery содержит, решение с помощью метода сплайсинга и многое другое. Однако все они кажутся сложными и раздражающими.

Что является наиболее чистым способом удаления элемента из массива javascript с объединенными возможностями javascript, jQuery и coffeescript? Мы не знаем индекс заранее. В коде:

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

В случае отсутствия хорошего встроенного метода, каков чистый способ расширения массивов javascript для поддержки такого метода? Если это поможет, я действительно использую массивы как наборы. Решения будут идеально работать в coffeescript с поддержкой jQuery. Кроме того, мне было наплевать на скорость, но вместо этого расставил приоритеты в простом и понятном коде.

8 ответов

Решение

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

Или сделать то же самое без grep jQuery:

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

Используя ванильный 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);

Это действительно легко с jQuery:

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

Заметки:

splice возвращает элементы, которые были удалены, так что не делайте myArray = myArray.splice(), myArray.splice(index,1) означает "удалить элемент массива по индексу 'index' из массива ".

$.inArray возвращает индекс в массиве искомого значения или -1, если значение отсутствует в массиве.

Это кажется довольно чистым и понятным; в отличие от других ответов, он учитывает возможность появления элемента более одного раза.

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 @

Если вы также используете библиотеку CoffeeScript создателя underscore.js, вот одна строка, которая будет работать хорошо:

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

или в js:

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

Хотя вы просите чистый подход с использованием Coffeescript или jQuery, я считаю, что самый чистый подход - использование фильтра метода vanilla javascript:

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

Он выглядит чище в coffeescript, но это переводит на тот же самый javascript, поэтому я считаю это только визуальным отличием, а не расширенной функцией coffeescript:

array.filter (item) -> item isnt match

Фильтр не поддерживается в старых браузерах, но Mozilla предоставляет полифилл, соответствующий стандарту ECMA. Я думаю, что это совершенно безопасный подход, потому что вы только приводите старые браузеры в соответствие с современными стандартами и не изобретаете никаких новых функций в своем полифилле.

Извините, если вы специально искали метод jQuery или только Coffeescript, но я думаю, что вы в основном просили использовать метод библиотеки, потому что вы не знали о методе только javascript.

Вот и все, библиотеки не нужны!

Это всего лишь небольшое изменение в удивительном решении Амира:

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

который возвращает элемент, если он есть в списке, так что вы можете сделать что-то вроде:

do_something 100 if a.remove(100)

Сценарий удаления кофе переводит на этот 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);
  }};

Вы можете просто попробовать утилиту grep в jQuery:

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

Здесь может быть проблема с производительностью, так как вы технически заставляете переменную ссылаться на новый массив; вы на самом деле не модифицируете оригинал. Предполагая, что на оригинал не ссылаются где-то еще, сборщик мусора должен взять или это довольно быстро. Это никогда не было проблемой для меня, но другие могут знать лучше. Ура!

Другие вопросы по тегам