2016-01-05 2 views
0

Я работаю над назначением, в котором мне предоставляется массив и различное количество аргументов. Я должен удалить все значения из исходного массива, которые имеют одинаковое значение этих аргументов. Вот мой код:Как удалить элементы в массиве, заданном аргументами в JS?

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

destroyer([3, 5, 1, 2, 2], 2, 3, 5) 

Я получаю правильный вывод для некоторых моделей массивов и аргументов, но для примера выше, он должен выводить только [1], но мой код вывода [1, 2]. Любая помощь будет оценена по достоинству. Благодарю.

+1

Можете ли вы предоставить запрос на это задание? Мне сложно понять, что вы собираетесь делать. – RobertAKARobin

ответ

1

Когда вы делаете .splice(), чтобы удалить элемент, он перемещает элементы после него вниз по пятну в массиве, и это приведет к тому, что цикл for пропустит следующий элемент, если он также будет соответствовать. Вы можете исправить это, уменьшив индекс цикла for после удаления элемента или, (мой любимый), вы можете просто перебрать массив назад, а затем .splice() не повлияет на будущие итерации.

Использование общей структуры кода, вот декремент решение:

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

 
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5); 
 
document.write(JSON.stringify(result));

Использование общей структуры кода, вот обратное решение итерации:

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

 
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5); 
 
document.write(JSON.stringify(result));


Вы также можете использовать другие вспомогательные массив функций использовать более нативной функциональности массива:

function destroyer(arr) { 
 
    var removes = Array.prototype.slice.call(arguments, 1); 
 
    return arr.filter(function(item) { 
 
     return removes.indexOf(item) === -1; 
 
    }); 
 
} 
 

 
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5); 
 
document.write(JSON.stringify(result));

Идущий с ES6 Набор для немного более потенциальной эффективности:

function destroyer(arr) { 
 
     var removes = new Set(Array.prototype.slice.call(arguments, 1)); 
 
     return arr.filter(function(item) { 
 
      return !removes.has(item); 
 
     }); 
 
    } 
 

 
    var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5); 
 
    document.write(JSON.stringify(result));

FYI, в предыдущем примере кода, я пытался сделать:

var removes = new Set(arguments); 

, как это кажется более чистым и который отлично работает в IE и Chrome, но ошибка в Firefox хранит его от работы там. Предполагается, что arguments в ES6 является итерируемым, что вы можете перейти к конструктору Set, но Firefox еще не реализовал его правильно. Существует open Firefox bug по этой теме, над которой работает. Итак, я поддержал этот пример кода, чтобы сделать копию в реальном массиве и передать массив в конструктор.


Другая возможность заключается в том, чтобы использовать остальные параметры ES6:

function destroyer(arr, ...items) { 
 
    var removes = new Set(items); 
 
    return arr.filter(function(item) { 
 
    return !removes.has(item); 
 
    }); 
 
} 
 

 
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5); 
 
document.write(JSON.stringify(result));

+1

Мне было любопытно, что решение Set и святая корова, это на десятки раз быстрее на больших массивах и даже с очень небольшим количеством элементов (менее 10 или 5), это почти всегда быстрее. Еще смешнее: реализация набора IE11 в два раза быстрее, чем у V8 ... [jsperf] (http://jsperf.com/setbeforefilter) – Shanoor

+0

@ masonc15 - Это ответ на ваш вопрос? – jfriend00

0

сделать это (используя indexOf и while цикл)

function destroyer(arr) { 
    for(var i = 1; i < arguments.length; i++) 
    { 
      var index = arr.indexOf(arguments[i]); 
      while(index != -1) 
      { 
       arr.splice(index, 1); 
       console.log(arr); 
       index = arr.indexOf(arguments[i]); 
      } 
    } 
    return arr; 
} 

вам нужно проверить его снова d, а не проверять его только один раз, если index не является -1

Смежные вопросы