Почему, если операторы блокируются в цикле while? - PullRequest
0 голосов
/ 11 июня 2019

У меня есть массив чисел с кучей дубликатов. Мне нужно от них избавиться, поэтому я поставил код:

  let dup = arr.filter((elem, pos)=> arr.indexOf(elem) !== pos);
  // dup Array contains the duplicate numbers
  arr = arr.filter((elem, pos)=> arr.indexOf(elem) == pos);
  //arr contains the whole array with duplicates
  let i = 0;
  let j = 0;
  while(i<arr.length){
    while(j<dup.length){
      if(arr[i] == dup[j]){
        arr.splice(i, 1);
        //the splice method resets the decrease the index of the array so
        i--;
      };
      j++;
    };
    i++
  }

Проблема в том, что if не запускается после первого совпадения. Так что массив splice первый дубликат, который он находит и останавливает. Как я могу это исправить?

Ответы [ 3 ]

3 голосов
/ 11 июня 2019

Проблема в том, что вы никогда не сбрасываете j.Вам нужно переместить это в цикл while (i ...).

let arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
console.log('arr', arr)

let dup = arr.filter((elem, pos)=> arr.indexOf(elem) !== pos);

console.log('dup', dup)

arr = arr.filter((elem, pos)=> arr.indexOf(elem) == pos)
console.log('new arr', arr)


let i = 0;
while(i<arr.length){
  let j = 0;
  while(j<dup.length){
    if(arr[i] == dup[j]){
      arr.splice(i, 1);
      i--;
    };
    j++;
  };
  i++
}

console.log('final arr', arr)

Но есть более простые способы сделать это.

Обновление

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

const singletons = (
  xs,
  dups = xs .filter ((x, i) => arr .indexOf (x) !== i)
) => xs .filter (x => dups .indexOf (x) < 0)

let arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]

console .log (
  singletons (arr)
)

Эта версия не изменяет ваш исходный массив, просто возвращает новый, содержащий только одноэлементные элементы (те, которые появляются только один раз в исходном списке.)

Объяснение

singletons - это функция, принимающая массив элемента определенного типа и возвращающая другой массив того же типа.Поскольку этот тип не является конкретным, я использую неспецифическое имя;довольно сильное соглашение сделать это xss отметкой, что это множественное число (т. е. массив из них.)

dups - это массив элементов, которые дублируются в вашем оригинале.Хотя я включил его в качестве параметра по умолчанию, мы могли бы так же легко создать его в теле функции, например так:

const singletons = (xs) => {
  const dups = xs .filter ((x, i) => arr .indexOf (x) !== i)
  return xs .filter (x => dups .indexOf (x) < 0)
}

Единственная причина, по которой я этого не сделал, - это то, что я, возможно, слишком любилтел одного выражения, таким образом избегая пары { - } и оператора return.Но между этими двумя подходами нет реальной разницы, за исключением того, что тот, который я представил, выполняет дополнительную работу, на которую я бы никогда не рассчитывал: если вы предоставите второй параметр, массив значений, то вместо удаления дубликатов,он удаляет все те элементы из вашего массива, которые также входят во второй, отдаленно напоминающие функцию разности множеств.

Основное преимущество этого подхода по сравнению с вашим подходом состоит в том, что он не разрушителен.Это не изменяет ваши исходные данные.Он также не имеет назначений, кроме параметра по умолчанию, поэтому в управлении состояниями нет путаницы.(«Куда я положу let j == 0?» - это не значимый вопрос.) Это делает его более устойчивым.

3 голосов
/ 11 июня 2019

С Получить все уникальные значения в массиве JavaScript (удалить дубликаты)

const myArray = ['a', 1, 'a', 2, '1'];

const unique = [...new Set(myArray)]; 

// output ["a", 1, 2, "1"]

или в виде функции

const unique = [...new Set(myArray)]
2 голосов
/ 11 июня 2019

Вам нужно установить j = 0 внутри первого цикла while, иначе он будет проходить через второй цикл while только один раз.

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

Мое решение для этого таково:

arr.forEach((e, i) => {
    dup.forEach((f, j) => {
        if(e==f){
            arr.splice(i, 1);
        }
    })
});

Надеюсь, у вас это получится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...