Obter todos os valores não exclusivos (por exemplo: duplicado / mais de uma ocorrência) em uma matriz

418

Preciso verificar uma matriz JavaScript para ver se existem valores duplicados. Qual é a maneira mais fácil de fazer isso? Eu só preciso encontrar quais são os valores duplicados - na verdade, não preciso dos índices ou quantas vezes eles são duplicados.

Eu sei que posso percorrer a matriz e verificar todos os outros valores para uma correspondência, mas parece que deve haver uma maneira mais fácil.

Pergunta semelhante:

Scott Saunders
fonte
22
Parece haver anos de confusão sobre o que essa pergunta faz. Eu precisava saber quais elementos da matriz foram duplicados: "Eu só preciso encontrar quais são os valores duplicados". A resposta correta NÃO deve remover duplicatas da matriz. Essa é a inversa do que eu queria: uma lista de duplicatas, não uma lista de elementos únicos.
22613 Scott Saunders

Respostas:

301

Você pode classificar a matriz e, em seguida, executá-la e verificar se o índice seguinte (ou anterior) é igual ao atual. Supondo que seu algoritmo de classificação seja bom, isso deve ser menor que O (n 2 ):

const findDuplicates = (arr) => {
  let sorted_arr = arr.slice().sort(); // You can define the comparing function here. 
  // JS by default uses a crappy string compare.
  // (we use slice to clone the array so the
  // original array won't be modified)
  let results = [];
  for (let i = 0; i < sorted_arr.length - 1; i++) {
    if (sorted_arr[i + 1] == sorted_arr[i]) {
      results.push(sorted_arr[i]);
    }
  }
  return results;
}

let duplicatedArray = [9, 9, 111, 2, 3, 4, 4, 5, 7];
console.log(`The duplicates in ${duplicatedArray} are ${findDuplicates(duplicatedArray)}`);

No caso, se você quiser retornar como uma função para duplicatas. Isso é para um tipo semelhante de caso.

Referência: https://stackoverflow.com/a/57532964/8119511

Swilliams
fonte
10
"Supondo que seu algoritmo de classificação seja bom, isso deve ser menor que O ^ 2". Especificamente, poderia ser O (n * log (n)).
ESRogs
83
Este script não funciona tão bem com mais de 2 duplicatas (por exemploarr = [9, 9, 9, 111, 2, 3, 3, 3, 4, 4, 5, 7];
Mottie
7
@ Williams Não acho que essas diretrizes digam nada sobre não usar i++. Em vez disso, eles dizem para não escrever j = i + +j. Duas coisas diferentes IMHO. Eu acho que i += 1é mais confuso do que a simples e bonito i++:)
Danilo Bargen
34
-1 Esta resposta está errada em muitos níveis. Antes de tudo, var sorted_arr = arr.sort()é inútil: arr.sort()transforma a matriz original (que é um problema por si só). Isso também descarta um elemento. (Executar o código acima O que acontece a 9.?) Solução mais limpa cc @dystroy Um seriaresults = arr.filter(function(elem, pos) { return arr.indexOf(elem) == pos; })
NullUserException
24
Todos: a pergunta pede para exibir os valores duplicados, não para removê-los. Não edite / quebre o código para tentar fazer algo que não está tentando fazer. O alerta deve mostrar os valores duplicados.
Scott Saunders
205

Se você deseja calcular as duplicatas, tente esta ótima solução:

function eliminateDuplicates(arr) {
  var i,
      len = arr.length,
      out = [],
      obj = {};

  for (i = 0; i < len; i++) {
    obj[arr[i]] = 0;
  }
  for (i in obj) {
    out.push(i);
  }
  return out;
}

Fonte: http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/

rapfaria
fonte
18
Esse é um bom código, mas infelizmente não faz o que estou pedindo.
Scott Saunders
67
O código acima (que é meu - esse é o meu blog) deixa você bem perto. Um pequeno ajuste e você está lá. Primeiro de tudo, você pode ver se arr.length e out.length são os mesmos. Se forem iguais, não há elementos duplicados. Mas você quer um pouco mais. Se você deseja "capturar" os enganadores à medida que eles acontecem, verifique se o comprimento da matriz aumenta após a linha obj [arr [i]] = 0. Bacana, hein? :-) Obrigado pelas boas palavras, Raphael Montanaro.
Nosredna
6
@MarcoDemaio: Uh, não, por que o código não funciona com espaços? Você pode colocar o que quiser em um nome de propriedade - simplesmente não pode usar a sintaxe de ponto para acessar espaços com espaços (nem adereços com vários outros caracteres que interromperiam a análise).
Gijs
4
@ Gijs: +1 você está certo. Eu não sabia disso. Mas ainda não funciona quando é uma matriz de objetos.
Marco Demaio 16/10
3
Esse algoritmo também tem o efeito colateral de retornar uma matriz classificada, que pode não ser o que você deseja.
assimétrica
166

Esta é a minha resposta do segmento duplicado (!):

Ao escrever esta entrada em 2014 - todos os exemplos foram for-loops ou jQuery. Javascript tem as ferramentas perfeitas para isso: classificar, mapear e reduzir.

Encontre itens duplicados

var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

var uniq = names
  .map((name) => {
    return {
      count: 1,
      name: name
    }
  })
  .reduce((a, b) => {
    a[b.name] = (a[b.name] || 0) + b.count
    return a
  }, {})

var duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1)

console.log(duplicates) // [ 'Nancy' ]

Sintaxe mais funcional:

@ Dmytro-Laptin apontou que algum código de código deve ser removido. Esta é uma versão mais compacta do mesmo código. Usando alguns truques do ES6 e funções de ordem superior:

const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

const count = names =>
  names.reduce((a, b) => ({ ...a,
    [b]: (a[b] || 0) + 1
  }), {}) // don't forget to initialize the accumulator

const duplicates = dict =>
  Object.keys(dict).filter((a) => dict[a] > 1)

console.log(count(names)) // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 }
console.log(duplicates(count(names))) // [ 'Nancy' ]

Christian Landgren
fonte
1
Esse é o tipo de solução que eu estava procurando. Se eu quisesse ter uma dúzia de repetições, isso seria muito fácil de escrever. A palavra-chave no OP foi "eficiente".
22416 Josh
@ChristianLandgren, onde a variável 'dict' é declarada? talvez 'count' deva ser usado?
Dmytro Laptin
4
Por favor, mantenha sua opinião enganosa para si mesmo (-1 por ser arrogante). Pessoalmente, estou cansado de pessoas confusas "curtas" e "eficientes", e postar frases sem questionar as performances. Programas curtos e JS modernos NÃO são melhores por natureza. Uso indevido típico da palavra "eficiente" aqui . Crença ingênua típica aqui (leia os comentários a seguir). Demonstração aqui .
leaf
1
@ folha - mantenha suas sugestões com suas próprias respostas. A solução que você editou não é legível, pode ter um desempenho (provavelmente não), mas mesmo assim - a legibilidade geralmente é mais importante que o desempenho na minha opinião. Mas o mais importante - não remova o código de outra pessoa para substituí-lo pelo seu sem motivo.
Christian Landgren
1
Respostas diferentes, sim, opiniões diferentes, acho que não.
folha de
64

Encontre valores duplicados em uma matriz

Essa deve ser uma das maneiras mais curtas de encontrar valores duplicados em uma matriz. Conforme solicitado especificamente pelo OP, isso não remove duplicatas, mas as encontra .

var input = [1, 2, 3, 1, 3, 1];

var duplicates = input.reduce(function(acc, el, i, arr) {
  if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc;
}, []);

document.write(duplicates); // = 1,3 (actual array == [1, 3])

Isso não precisa ser classificado ou qualquer estrutura de terceiros. Também não precisa de loops manuais. Funciona com todos os valores indexOf () (ou, para ser mais claro: o operador de comparação estrita ) suporta.

Por causa de replace () e indexOf (), ele precisa pelo menos do IE 9.

gripe
fonte
7
ES6 arrow / versão simples / pura:const dupes = items.reduce((acc, v, i, arr) => arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc, [])
ZephDavies 29/11
30

Você pode adicionar essa função ou ajustá-la e adicioná-la ao protótipo de matriz do Javascript:

Array.prototype.unique = function () {
    var r = new Array();
    o:for(var i = 0, n = this.length; i < n; i++)
    {
        for(var x = 0, y = r.length; x < y; x++)
        {
            if(r[x]==this[i])
            {
                alert('this is a DUPE!');
                continue o;
            }
        }
        r[r.length] = this[i];
    }
    return r;
}

var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9];
var unique = arr.unique();
alert(unique);
karim79
fonte
Esta é a melhor solução, mas tenha cuidado ao adicioná-la ao protótipo da matriz, pois isso atrapalha o IE se você percorrer os valores.
Sampsa Suoninen 12/10
@RoyTinker perl apoia-los também, mas eu não tinha idéia javascript fez
Luke H
1
Não faz o que o OP solicitou, retorna as duplicatas.
RWC
27

ATUALIZADO: O seguinte usa uma estratégia combinada otimizada. Ele otimiza as pesquisas primitivas para se beneficiar do tempo de pesquisa do hash O (1) (a execução uniqueem uma matriz de primitivas é O (n)). As pesquisas de objeto são otimizadas, marcando objetos com um ID exclusivo, enquanto iteram, de modo que a identificação de objetos duplicados também seja O (1) por item e O (n) para toda a lista. A única exceção são os itens congelados, mas esses são raros e um fallback é fornecido usando uma matriz e indexOf.

var unique = function(){
  var hasOwn = {}.hasOwnProperty,
      toString = {}.toString,
      uids = {};

  function uid(){
    var key = Math.random().toString(36).slice(2);
    return key in uids ? uid() : uids[key] = key;
  }

  function unique(array){
    var strings = {}, numbers = {}, others = {},
        tagged = [], failed = [],
        count = 0, i = array.length,
        item, type;

    var id = uid();

    while (i--) {
      item = array[i];
      type = typeof item;
      if (item == null || type !== 'object' && type !== 'function') {
        // primitive
        switch (type) {
          case 'string': strings[item] = true; break;
          case 'number': numbers[item] = true; break;
          default: others[item] = item; break;
        }
      } else {
        // object
        if (!hasOwn.call(item, id)) {
          try {
            item[id] = true;
            tagged[count++] = item;
          } catch (e){
            if (failed.indexOf(item) === -1)
              failed[failed.length] = item;
          }
        }
      }
    }

    // remove the tags
    while (count--)
      delete tagged[count][id];

    tagged = tagged.concat(failed);
    count = tagged.length;

    // append primitives to results
    for (i in strings)
      if (hasOwn.call(strings, i))
        tagged[count++] = i;

    for (i in numbers)
      if (hasOwn.call(numbers, i))
        tagged[count++] = +i;

    for (i in others)
      if (hasOwn.call(others, i))
        tagged[count++] = others[i];

    return tagged;
  }

  return unique;
}();

Se você tiver o ES6 Collections disponível, haverá uma versão muito mais simples e significativamente mais rápida. (shim para o IE9 + e outros navegadores aqui: https://github.com/Benvie/ES6-Harmony-Collections-Shim )

function unique(array){
  var seen = new Set;
  return array.filter(function(item){
    if (!seen.has(item)) {
      seen.add(item);
      return true;
    }
  });
}

fonte
mesmo? por que responder a uma pergunta que foi resolvida há mais de 2 anos?
Rene Pot
3
Eu estava respondendo a outra pergunta e, aparentemente, acidentalmente clicou em alguém vinculando a esta, chamando-a de duplicata, e acabou clonando minha resposta e confundindo o inferno fora de mim. Eu edito muito minhas coisas.
16
Eu acho que é legal com soluções diferentes. Não importa que o tópico seja antigo e resolvido, pois ainda é possível criar maneiras diferentes de fazer isso. É um problema típico da ciência da computação.
Emil Vikström
Você pode querer mencionar que este se baseia em métodos de matriz ES5 que não são implementadas no IE <9.
Tim Baixo
24

ATUALIZADO: Uma linha curta para obter as duplicatas:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) !== i) // [2, 4]

Para obter a matriz sem duplicatas, basta inverter a condição:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) === i) // [1, 2, 3, 4]

Eu simplesmente não pensei filter()na minha antiga resposta abaixo;)


Quando tudo que você precisa é verificar se não há duplicatas, conforme solicitado nesta pergunta, você pode usar o every()método:

[1, 2, 3].every((e, i, a) => a.indexOf(e) === i) // true

[1, 2, 1].every((e, i, a) => a.indexOf(e) === i) // false

Observe que every()não funciona no IE 8 e abaixo.

Laurent Payot
fonte
1
Não faz o que o OP solicitou, retorna as duplicatas.
RWC
É verdade que atualizei minha resposta para corrigir isso.
Laurent Payot
Solução real! thnaks
Jeremy Piednoel
21
var a = ["a","a","b","c","c"];

a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})
Angel Calderaro Pacciott, David
fonte
Isso parece funcionar, mas você provavelmente deve incluir algum texto descrevendo como funciona.
The DIMM Reaper
1
Não funcionará se houver mais 2 ocorrências de um valor duplicado.
vasa
1
Isso é elegante e simples. Eu amo isso. Para aqueles que querem descobrir como eles funcionam, eu criei uma essência que mostra como mostrar duplicatas e eliminar duplicatas. Veja aqui: gist.github.com/jbcoder/f1c616a32ee4d642691792eebdc4257b
Josh
@TheDIMMReaper para o segundo 'a'na matriz, a função de filtro no interior do index == 1, enquanto queself.indexOf('a') == 0
Sergiy Ostróvski
19

Isso deve fazer o que você quer, apenas as duplicatas.

function find_duplicates(arr) {
  var len=arr.length,
      out=[],
      counts={};

  for (var i=0;i<len;i++) {
    var item = arr[i];
    counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
    if (counts[item] === 2) {
      out.push(item);
    }
  }

  return out;
}

find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order.
Daniel Beardsley
fonte
13

usando underscore.js

function hasDuplicate(arr){
    return (arr.length != _.uniq(arr).length);
}
Marco Allori
fonte
9

ES2015

//          🚩🚩   🚩                 🚩 
var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    unique;

// Combine all the arrays to a single one
unique = arr.concat(arr2, arr3)

// create a new (dirty) Array with only the unique items
unique = unique.map((item,i) => unique.includes(item, i+1) ? item : '' )

// Cleanup - remove duplicate & empty items items 
unique = [...new Set(unique)].filter(n => n)

console.log(unique)


Encontre valores exclusivos de 3 matrizes (ou mais):

Array.prototype.unique = function () {
    var arr = this.sort(), i; // input must be sorted for this to work
    for( i=arr.length; i--; )
      arr[i] === arr[i-1] && arr.splice(i,1); // remove duplicate item

    return arr;
}

var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,9],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    // merge arrays & call custom Array Prototype - "unique"
    unique = arr.concat(arr2, arr3).unique();

console.log(unique);  // [22, 50, 12, 511, 2, 1, 9, 5, 8, 7, 3, 6, 4]

Apenas um polyfill para índice de matriz

if (!Array.prototype.indexOf){
   Array.prototype.indexOf = function(elt /*, from*/){
     var len = this.length >>> 0;

     var from = Number(arguments[1]) || 0;
     from = (from < 0) ? Math.ceil(from) : Math.floor(from);
     if (from < 0)
        from += len;

     for (; from < len; from++){
        if (from in this && this[from] === elt)
           return from;
     }
     return -1;
  };
}

Solução jQuery usando "inArray":

if( $.inArray(this[i], arr) == -1 )

em vez de adicionar o Array.prototype.indexOf

vsync
fonte
+1 porque é definitivamente mais legível o código usando Array.indexOf, mas infelizmente parece mais lento do que usar um loop aninhado simples. Mesmo em navegadores que implementam Array.indexOf de forma negativa como o FF. Por favor, dê uma olhada nestes testes que fiz aqui: jsperf.com/array-unique2 e deixe-me saber seus pensamentos.
Marco Demaio
@shekhardesigner - resposta atualizada. "r" é a matriz que você procurar no
vsync
@ vsync Eu tive que inicializar, var r = [];para obter o seu código funcionando. E funcionou como charme.
Shekhar K. Sharma
@shekhardesigner - Sinto muito por mistura, para a solução de matriz Prototype você não precisa de uma rvariável
vsync
2
Não faz o que o OP solicitou, retorna as duplicatas.
RWC
8

Aqui está a minha solução simples e de uma linha.

Ele procura primeiro elementos não exclusivos e, em seguida, torna a matriz encontrada única com o uso de Set

Portanto, temos uma série de duplicatas no final.

var array = [1, 2, 2, 3, 3, 4, 5, 6, 2, 3, 7, 8, 5, 22, 1, 2, 511, 12, 50, 22];

console.log([...new Set(
  array.filter((value, index, self) => self.indexOf(value) !== index))]
);

Oleg Abrazhaev
fonte
7

Esta é a minha proposta (ES6):

let a = [1, 2, 3, 4, 2, 2, 4, 1, 5, 6]
let b = [...new Set(a.sort().filter((o, i) => o !== undefined && a[i + 1] !== undefined && o === a[i + 1]))]

// b is now [1, 2, 4]
lukaszkups
fonte
1
Isso relatará que uma única ocorrência de undefinedé uma duplicata.
Dem Pilafian
1
@DemPilafian obrigado, atualizado
lukaszkups
6
var a = [324,3,32,5,52,2100,1,20,2,3,3,2,2,2,1,1,1].sort();
a.filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});

ou quando adicionado ao prototyp.chain da matriz

//copy and paste: without error handling
Array.prototype.unique = 
   function(){return this.sort().filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});}

Veja aqui: https://gist.github.com/1305056

Lorenz Lo Sauer
fonte
1
A função de filtro deve retornar verdadeiro ou falso, não o próprio elemento. Filtrar uma matriz contendo 0 não os teria retornado.
Mflodin
Além disso, suponho i&&que isso evite sair dos limites da matriz, mas também significa que o primeiro elemento na matriz classificada não será incluído. No seu exemplo, não há 1na matriz resultante. return i&&v!==o[i-1]?v:0;return v!==o[i-1];
Ou
6

Maneira rápida e elegante usando a desestruturação de objetos es6 e reduza

É executado em O (n) (1 iteração sobre a matriz) e não repete valores que aparecem mais de 2 vezes

const arr = ['hi', 'hi', 'hi', 'bye', 'bye', 'asd']
const {
  dup
} = arr.reduce(
  (acc, curr) => {
    acc.items[curr] = acc.items[curr] ? acc.items[curr] += 1 : 1
    if (acc.items[curr] === 2) acc.dup.push(curr)
    return acc
  }, {
    items: {},
    dup: []
  },
)

console.log(dup)
// ['hi', 'bye']

Lucas Janon
fonte
5

Aqui está a solução mais simples que eu poderia pensar:

    const arr = [-1, 2, 2, 2, 0, 0, 0, 500, -1, 'a', 'a', 'a']

    const filtered = arr.filter((el, index) => arr.indexOf(el) !== index)
    // => filtered = [ 2, 2, 0, 0, -1, 'a', 'a' ]

    const duplicates = [...new Set(filtered)]

    console.log(duplicates)
    // => [ 2, 0, -1, 'a' ]

É isso aí.

Nota:

  1. Funciona com qualquer número 0, incluindo strings e números negativos, por exemplo -1- Pergunta relacionada: Obtenha todos os valores exclusivos em uma matriz JavaScript (remova duplicatas)

  2. A matriz original arré preservada ( filterretorna a nova matriz em vez de modificar a original)

  3. A filteredmatriz contém todas as duplicatas; ele pode também conter mais do que um mesmo valor (por exemplo, a matriz é filtrada aqui [ 2, 2, 0, 0, -1, 'a', 'a' ])

  4. Se você deseja obter apenas valores duplicados (não deseja ter várias duplicatas com o mesmo valor), pode usar [...new Set(filtered)](o ES6 tem um conjunto de objetos que pode armazenar apenas valores exclusivos)

Espero que isto ajude.

Nikola Jovanovic
fonte
5

JS de baunilha mais curto :

[1,1,2,2,2,3].filter((v,i,a) => a.indexOf(v) !== i) // [1, 2, 2]
galinhas
fonte
4

Aqui está uma maneira muito leve e fácil:

var codes = dc_1.split(',');
var i = codes.length;
while (i--) {
  if (codes.indexOf(codes[i]) != i) {
    codes.splice(i,1);
  }
}
Brandon Ferrara
fonte
Melhor resposta. E se o usuário quiser uma matriz de elementos duplicados, atualizei o código @brandon var i = codes .length; var duplicado = []; while (i--) {if (códigos .indexOf (códigos [i])! = i) {if (duplicate.indexOf (códigos [i]) === -1) {duplicate.push (arr [i]) ; } codes.splice (i, 1); }}
Himanshu Shekhar
4

Com o ES6 (ou usando Babel ou Typescipt), você pode simplesmente:

var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1);

https://es6console.com/j58euhbt/

tocqueville
fonte
Cheguei à mesma sintaxe, de forma independente, e estava prestes a adicioná-la como uma solução quando encontrei essa. Provavelmente não é o mais econômico, mas é simples.
nize
4

Código simples com sintaxe ES6 (retorne uma matriz classificada de duplicatas):

let duplicates = a => {d=[]; a.sort((a,b) => a-b).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d};

Como usar:

duplicates([1,2,3,10,10,2,3,3,10]);
hóspede
fonte
1
.filter () seria muito mais simples
tocqueville
4

um forro

var arr = [9,1,2,4,3,4,9]
console.log(arr.filter((ele,indx)=>indx!==arr.indexOf(ele))) //get the duplicates
console.log(arr.filter((ele,indx)=>indx===arr.indexOf(ele))) //remove the duplicates

sravan ganji
fonte
o que indx!faz para o primeiro exemplo?
saylestyler
1
@saylestyler Hehe, isso significa indx !== ...- desigualdade estrita.
Daria
adicionando apenas para a gama de objectosresult.filter((ele,indx) => indx !== result.map(e => e.name).indexOf(ele.name));
x-magix
4

Essa resposta também pode ser útil, pois utiliza o reduce operador / método js para remover duplicatas da matriz.

const result = [1, 2, 2, 3, 3, 3, 3].reduce((x, y) => x.includes(y) ? x : [...x, y], []);

console.log(result);

Divyanshu Rawat
fonte
3
agora podemos apenas fazer new Set([1, 2, 2, 3, 3, 3, 3])para remover duplicatas
kimbaudi
3

A função a seguir (uma variação da função deleteDuplicates já mencionada) parece fazer o truque, retornando teste2,1,7,5 para a entrada ["teste", "teste2", "teste2", 1, 1, 1, 2 , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

Observe que o problema é mais estranho no JavaScript do que na maioria dos outros idiomas, porque uma matriz JavaScript pode conter praticamente qualquer coisa. Observe que as soluções que usam classificação podem precisar fornecer uma função de classificação apropriada - ainda não tentei essa rota.

Essa implementação específica funciona para (pelo menos) seqüências de caracteres e números.

function findDuplicates(arr) {
    var i,
        len=arr.length,
        out=[],
        obj={};

    for (i=0;i<len;i++) {
        if (obj[arr[i]] != null) {
            if (!obj[arr[i]]) {
                out.push(arr[i]);
                obj[arr[i]] = 1;
            }
        } else {
            obj[arr[i]] = 0;            
        }
    }
    return out;
}
Nosredna
fonte
3

Somente ES5 (ou seja, ele precisa de um polyfill de filtro () para o IE8 e abaixo):

var arrayToFilter = [ 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3 ];

arrayToFilter.
    sort().
    filter( function(me,i,arr){
       return (i===0) || ( me !== arr[i-1] );
    });
Gotofritz
fonte
Eu gosto desta solução simples. Se você deseja as duplicatas, no entanto, é necessário primeiro encontrá-las e depois tornar a lista de duplicatas exclusiva. [0, 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3] .sort (). Filter (function (me, i, arr) {return (i! == 0 ) && (me == arr [i-1]);}). filter (função (me, i, arr) {return (i === 0) || (me! == arr [i-1]) ;});
Greg
3

var arr = [2, 1, 2, 2, 4, 4, 2, 5];

function returnDuplicates(arr) {
  return arr.reduce(function(dupes, val, i) {
    if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) {
      dupes.push(val);
    }
    return dupes;
  }, []);
}

alert(returnDuplicates(arr));

Essa função evita a etapa de classificação e usa o método reduzem () para enviar duplicatas para uma nova matriz, se ela ainda não existir.

vasa
fonte
3

Essa é provavelmente a maneira mais rápida de remover permanentemente as duplicatas de uma matriz 10 vezes mais rápido que a maioria das funções aqui. & 78x mais rápido no safari

function toUnique(a,b,c){//array,placeholder,placeholder
 b=a.length;
 while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
toUnique(array);
console.log(array);
  1. Teste: http://jsperf.com/wgu
  2. Demonstração: http://jsfiddle.net/46S7g/
  3. Mais: https://stackoverflow.com/a/25082874/2450730

se você não conseguir ler o código acima, pergunte, leia um livro em javascript ou aqui estão algumas explicações sobre códigos mais curtos. https://stackoverflow.com/a/21353032/2450730

EDITAR Conforme declarado nos comentários, esta função retorna uma matriz com únicos, mas a pergunta pede para encontrar as duplicatas. nesse caso, uma simples modificação dessa função permite inserir as duplicatas em uma matriz e, em seguida, usar a função anterior toUniqueremove as duplicatas das duplicatas.

function theDuplicates(a,b,c,d){//array,placeholder,placeholder
 b=a.length,d=[];
 while(c=--b)while(c--)a[b]!==a[c]||d.push(a.splice(c,1))
}
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];

toUnique(theDuplicates(array));
cocco
fonte
7
"se você não conseguir ler o código acima, pergunte, leia um livro em javascript" Há muito código em excesso nesta resposta. Nomear as variáveis ​​como a, b, c dificulta a leitura do código. O abandono do aparelho torna ainda pior.
Rio Williamson
A maioria das minhas respostas é baseada em economia de desempenho e espaço (outras soluções já foram publicadas) ... se você não gostar disso, aprenda javascript, leia um livro js ... ou use jquery ... tem muito mais respostas se você procurar uma solução simples. Se você realmente quer aprender algo, fico feliz em explicar a letra do código por letra. Como não consigo ver uma pergunta real no seu comentário, acho que você está apenas procurando um motivo para rebaixar minha resposta .... continue ... não tenho problema com isso. Faça uma pergunta real ou me diga algo que não funciona com meu código.
Cocco
9
Não há nada tecnicamente errado com seu código. Dito isto, nomear variáveis ​​a, b, c, d, etc. e encadear while loops dificulta a leitura do código. Portanto, o código falha ao ensinar qualquer coisa.
River Williamson
3

Usando "includes" para testar se o elemento já existe.

var arr = [1, 1, 4, 5, 5], darr = [], duplicates = [];

for(var i = 0; i < arr.length; i++){
  if(darr.includes(arr[i]) && !duplicates.includes(arr[i]))
    duplicates.push(arr[i])
  else
    darr.push(arr[i]);
}

console.log(duplicates);
<h3>Array with duplicates</h3>
<p>[1, 1, 4, 5, 5]</p>
<h3>Array with distinct elements</h3>
<p>[1, 4, 5]</p>
<h3>duplicate values are</h3>
<p>[1, 5]</p>

Srichakradhar
fonte
O código retorna elementos distintos, mas não leva ao resultado fornecido. Forneça o código correto completo.
RWC 14/01
3

O ES6 oferece a estrutura de dados do conjunto, que é basicamente uma matriz que não aceita duplicatas. Com a estrutura de dados do conjunto, há uma maneira muito fácil de encontrar duplicatas em uma matriz (usando apenas um loop).

Aqui está o meu código

function findDuplicate(arr) {
var set = new Set();
var duplicates = new Set();
  for (let i = 0; i< arr.length; i++) {
     var size = set.size;
     set.add(arr[i]);
     if (set.size === size) {
         duplicates.add(arr[i]);
     }
  }
 return duplicates;
}
Roysh
fonte
3

Acabei de descobrir uma maneira simples de conseguir isso usando um filtro Array

    var list = [9, 9, 111, 2, 3, 4, 4, 5, 7];
    
    // Filter 1: to find all duplicates elements
    var duplicates = list.filter(function(value,index,self) {
       return self.indexOf(value) !== self.lastIndexOf(value) && self.indexOf(value) === index;
    });
    
    console.log(duplicates);

alaahd
fonte
3

Seguir a lógica será mais fácil e rápido

// @Param:data:Array that is the source 
// @Return : Array that have the duplicate entries
findDuplicates(data: Array<any>): Array<any> {
        return Array.from(new Set(data)).filter((value) => data.indexOf(value) !== data.lastIndexOf(value));
      }

Vantagens:

  1. Linha única :-P
  2. Toda a estrutura de dados incorporada, ajudando a melhorar a eficiência
  3. Mais rápido

Descrição da lógica:

  1. Convertendo para definir para remover todas as duplicatas
  2. Iterando Através dos Valores Definidos
  3. Com cada verificação de valor definido na matriz de origem, a condição "valores primeiro índice não é igual ao último índice" ==> Em seguida, inferida como duplicada, caso contrário, ela é 'única'

Nota: os métodos map () e filter () são eficientes e mais rápidos.

PranavKAndro
fonte
1
Testei isso ... muito rápido. e faz sentido .. desejo que eu pensei sobre isso
Michael Rhema