удалить из массива все элементы, встречающиеся более одного раза - PullRequest
0 голосов
/ 30 октября 2018

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

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

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];

const uniqueArray = a.filter(function(item, pos) {
  return a.indexOf(item) == pos;
})

console.log(uniqueArray)

Я хочу, чтобы мой uniqueArray был

['Ronaldo', 'Maradona', 'Messi'];

Ответы [ 5 ]

0 голосов
/ 30 октября 2018

Вы можете использовать Map, чтобы подсчитать, сколько раз появляется каждая запись, а затем брать только те, которые делают это только один раз.

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];

const uniqueArray = onlyUniqueItems(a);

console.log(uniqueArray)


function onlyUniqueItems(array) {
  const map = new Map();
  const result = [];
  
  array.forEach(item => {
    let amount = map.get(item) || 0;
    map.set(item, ++amount); //pre-increment and then set the amount
  });
  
  map.forEach((amount, item) => {
    if (amount == 1) {
      result.push(item);
    }
  });
  
  return result;
}

Это будет работать в O (2n), так как вам нужно будет сделать не более двух сканов. Вы можете достичь аналогичного результата, используя простой объект и задавая для него значения ключей, но у Map есть преимущество, заключающееся в сохранении типа ваших элементов, тогда как простой объект преобразует все ключи в строки:

const a = [1, 2, 3, 3, "4", "4", "5"];

const uniqueArray = onlyUniqueItems(a);
const uniqueArrayUsingObject = onlyUniqueItemsUsingObject(a);

console.log(uniqueArray)
console.log(uniqueArrayUsingObject)


function onlyUniqueItems(array) {
  const map = new Map();
  const result = [];
  
  //count occurences
  array.forEach(item => {
    let amount = map.get(item) || 0;
    map.set(item, ++amount); //pre-increment and then set the amount
  });
  
  //extract only the items that show once
  map.forEach((amount, item) => {
    if (amount == 1) {
      result.push(item);
    }
  });
  
  return result;
}


function onlyUniqueItemsUsingObject(array) {
  const map = {};
  const result = [];
  
  //count occurences
  array.forEach(item => {
    let amount = map[item] || 0;
    map[item] = ++amount; //pre-increment and then set the amount
  });
  
  //extract only the items that show once
  Object.entries(map).forEach(([item, amount]) => {
    if (amount == 1) {
      result.push(item);
    }
  });
  
  return result;
}
0 голосов
/ 30 октября 2018

Наивным способом было бы проверить более одного случая:

   a.filter((el, i) => !(a.indexOf(el) !== i || a.indexOf(el, i) > -1)));

Или более сложный с несколькими наборами (но O (n)):

  const found = new Set, values = new Set;

  for(const el of a)
   if(!found.has(el)) {
     found.add(el);
     values.add(el);
   } else if(values.has(el) {
     values.delete(el);
   }
 }

 const result = [...values.values()];
0 голосов
/ 30 октября 2018

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

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];

const uniqueArray = a.filter(function(item, pos) {
  var c = a.filter(i => i==item).length;
  return a.indexOf(item) == pos && c <= 1;
})

console.log(uniqueArray);

Хотя лучшим решением будет сравнение индекса текущего элемента массива с Array.prototype.indexOf () и Array.prototype.lastIndexOf () :

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];

const uniqueArray = a.filter(function(item, pos) {
  return a.indexOf(item) === a.lastIndexOf(item);
})

console.log(uniqueArray);
0 голосов
/ 30 октября 2018

Вкратце: сохраните значение, если позиция первого вхождения элемента (indexOf) также является последней позицией элемента в массиве (lastIndexOf).

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

const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 
           'Pele', 'Messi', 'Jair', 'Baggio', 'Messi', 
           'Seedorf'];

const uniqueArray = a.filter(function(item, pos) {
  return a.lastIndexOf(item) == a.indexOf(item);
});

console.log(uniqueArray);
/* output:  ["Ronaldo", "Maradona", "Jair", "Baggio", "Seedorf"] */

Codepen Demo

0 голосов
/ 30 октября 2018

Почему бы не использовать Set?

const theSet = new Set(a);
const values = set.values();
const uniqueArray = Array.from(values);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...