Obtenez toutes les valeurs non uniques (c.-à-d.: dupliquer/plus d'une occurrence) dans un tableau

je dois vérifier un tableau JavaScript pour voir s'il y a des valeurs dupliquées. Quelle est la meilleure façon de le faire? Je dois juste trouver quelles sont les valeurs dupliquées - Je n'ai pas vraiment besoin de leurs index ou combien de fois ils sont dupliqués.

je sais que je peux boucler le tableau et vérifier toutes les autres valeurs pour une correspondance, mais il semble qu'il devrait y avoir un moyen plus facile. Des idées? Merci!

question similaire:

319
demandé sur Samuel Liew 2009-05-08 20:48:31

30 réponses

vous pouvez trier le tableau et ensuite l'exécuter et voir si l'index suivant (ou précédent) est le même que le courant. En supposant que votre algorithme de tri est bon, cela devrait être moins que O(n 2 ):

var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7];
var 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)
var results = [];
for (var i = 0; i < sorted_arr.length - 1; i++) {
    if (sorted_arr[i + 1] == sorted_arr[i]) {
        results.push(sorted_arr[i]);
    }
}

console.log(results);
238
répondu swilliams 2017-11-09 03:45:23

si vous voulez éliminer les doublons, essayez cette grande solution:

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

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

202
répondu rapfaria 2018-06-05 02:14:24

C'est ma réponse du fil dupliqué (!):

s'est lassé de voir tous les mauvais exemples Avec for-loops ou jQuery. Javascript a les outils parfaits pour cela de nos jours: trier, cartographier et réduire.

trouver des articles en double

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' ]

syntaxe plus fonctionnelle:

@Dmytro-Laptin a fait remarquer qu'un certain code devait être supprimé. C'est une version compacte du même code. Utilisation de quelques astuces ES6 et fonctions d'ordre supérieur:

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

const count = names => 
  names.reduce((a, b) => 
    Object.assign(a, {[b]: (a[b] || 0) + 1}), {})

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' ]

Utilisant La Fonction.prototype.bind:

  // prep
  const arr = Array.from('Learn more javascript dude');
  const counter = (prev, next) => Object.assign(prev, { [next] : (prev[next] || 0) + 1 });
  const singles = function(key){ return this[key] === 1 };
  const multiples = function(key){ return this[key] > 1 };

  // work
  const counted = arr.reduce(counter, {});
  const filtered = Object.keys(counted).filter(multiples.bind(counted));

  //[ "e", "a", "r", " ", "d" ]
  console.log(filtered);
132
répondu Christian Landgren 2017-03-06 20:08:14

trouver des valeurs dupliquées dans un tableau

ce devrait être l'un des moyens les plus courts pour trouver réellement des valeurs dupliquées dans un tableau. Comme demandé spécifiquement par L'OP, cela ne supprime pas les doublons mais les trouve .

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])

cela n'a pas besoin de tri ou de tout cadre tiers. Il n'a pas non plus besoin de boucles manuelles. Il fonctionne avec toutes les valeurs indexOf() (ou pour être plus clair: le opérateur de comparaison stricte ) supports.

en Raison de réduire() et indexOf() il faut au moins IE 9.

30
répondu flu 2016-07-22 09:02:31

vous pouvez ajouter cette fonction, ou la modifier et l'ajouter au prototype du tableau de 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);
29
répondu karim79 2009-05-08 16:54:30

mise à JOUR: Les utilisations suivantes optimiser une stratégie combinée. Il optimise les recherches primitives pour profiter du temps de recherche de hash O(1) (Lancer unique sur un tableau de primitives est O(n)). Les recherches d'objets sont optimisées en étiquetant les objets avec un id unique tout en itérant à travers ainsi l'identification des objets dupliqués est également O(1) par article et O(n) pour la liste entière. La seule exception est les articles qui sont gelés, mais ils sont rares et un repli est fourni en utilisant un tableau et 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;
}();

si vous avez des Collections ES6 disponibles, alors il ya une version beaucoup plus simple et beaucoup plus rapide. (shim pour IE9+ et autres navigateurs ici: 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;
    }
  });
}
27
répondu 2012-06-12 18:12:34

ça devrait vous donner ce que vous voulez, juste les doubles.

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.
16
répondu Daniel Beardsley 2016-06-30 01:35:27

en utilisant le trait de soulignement.js

function hasDuplicate(arr){
    return (arr.length != _.uniq(arr).length);
}
13
répondu Marconi 2012-09-04 16:12:28
var a = ["a","a","b","c","c"];

a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})
10
répondu Angel David Calderaro Pacciott 2015-06-24 04:11:00
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 lorsqu'il est ajouté au prototyp.chaîne de réseau

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

voir ici: https://gist.github.com/1305056

6
répondu Lorenz Lo Sauer 2012-01-10 04:04:29

quand tout ce que vous avez besoin est de vérifier qu'il n'y a pas de duplicata comme demandé dans cette question vous pouvez utiliser la every() méthode:

[1, 2, 3].every(function(elem, i, array){return array.lastIndexOf(elem) === i}) // true

[1, 2, 1].every(function(elem, i, array){return array.lastIndexOf(elem) === i}) // false

notez que every() ne fonctionne pas pour IE 8 et inférieur.

j'utilise lastIndexOf() parce qu'il pourrait être plus efficace que indexOf() si la fonction rappels effectués par un every() dans l'ordre des index, mais ce n'est pas prouvée.

In CoffeeScript je suis en utilisant ceci:

Array::duplicates = -> not @every((elem, i, array) -> array.lastIndexOf(elem) is i)

[1, 2, 3].duplicates() // false
[1, 2, 1].duplicates() // true
5
répondu Laurent Payot 2017-05-23 12:10:29

trouver des valeurs uniques à partir de 3 tableaux (ou plus):

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],
    unique = arr.concat(arr2, arr3).unique();

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

Juste un polyfill pour tableau indexOf pour les vieux navigateurs:

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

jQuery solution à l'aide de "inArray":

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

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

au lieu d'ajouter le tableau.prototype.indexOf'

5
répondu vsync 2018-06-17 18:25:10

code Simple avec ES6 syntaxe (retour tableau trié de doublons):

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

comment utiliser:

duplicates([1,2,3,10,10,2,3,3,10]);
4
répondu guest 2017-09-19 09:13:22

la fonction suivante (une variante de la fonction éliminateuplicates déjà mentionnée) semble faire l'affaire, retournant test2,1, 7, 5 pour l'Entrée ["test", "test2", "test2"", 1, 1, 1, 2, 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

notez que le problème est plus étrange dans JavaScript que dans la plupart des autres langues, parce qu'un tableau JavaScript peut contenir à peu près n'importe quoi. Notez que les solutions qui utilisent le tri pourraient avoir besoin de fournir une fonction de tri appropriée--I n'ai pas essayé cette voie encore.

cette implémentation particulière fonctionne pour (au moins) les chaînes et les nombres.

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;
}
3
répondu Nosredna 2009-05-09 01:02:41

voici un moyen très léger et facile:

var codes = dc_1.split(',');
var i = codes.length;
while (i--) {
  if (codes.indexOf(codes[i]) != i) {
    codes.splice(i,1);
  }
}
3
répondu Brandon Ferrara 2013-05-02 19:15:27

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

cette fonction évite l'étape de tri et utilise la méthode reduce() pour pousser les doublons vers un nouveau tableau si celui-ci n'existe pas déjà.

3
répondu vasa 2015-11-03 00:59:04

utilisant" includes " pour vérifier si l'élément existe déjà.

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>
3
répondu Srichakradhar 2017-01-15 20:09:59

ES6 offre la structure de données Set qui est fondamentalement un tableau qui n'accepte pas les doublons. Avec la structure de données Set, il y a un moyen très simple de trouver des doublons dans un tableau (en n'utilisant qu'une seule boucle).

Voici mon code

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;
}
3
répondu Roysh 2017-04-12 08:52:14

avec ES6 (ou en utilisant Babel ou Typescipt) vous pouvez simplement faire:

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

https://es6console.com/j58euhbt /

3
répondu tocqueville 2017-07-17 17:15:15

je viens de trouver un moyen simple de réaliser ceci en utilisant un filtre à Réseau.""

    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);
3
répondu alaahd 2018-03-07 12:14:48

voici ma solution simple et une ligne.

il ne recherche Pas d'éléments uniques d'abord, puis rend found array unique avec L'utilisation de Set.

donc nous avons un tableau de doublons à la fin.

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))]
);
3
répondu Oleg Abrazhaev 2018-08-13 13:53:00

Rapidement et de manière élégante à l'aide de es6 objet de déstructuration et de réduire les

il s'exécute en O (n) (1 itération sur le tableau) et ne répète pas les valeurs qui apparaissent plus de 2 fois

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']
3
répondu Lucas Janon 2018-08-28 13:33:45

juste pour ajouter une théorie à ce qui précède.

trouver des doublons a une limite inférieure de O(N*log(n) dans le modèle de comparaison. Donc, en théorie, vous ne pouvez pas faire mieux que d'abord trier puis passer par le liste séquentielle supprimant tous les doublons que vous trouvez.

Si vous voulez trouver les doublons en linéaire (O(n)) attendu de temps, vous pourriez hachez chaque élément de la liste; s'il y a une collision, supprimez/étiquetez-le comme un doublon, et de continuer.

2
répondu SplittingField 2009-05-09 00:12:16

ES5 seulement (c'est à dire, il a besoin d'un filtre() polyfill pour IE8 et ci-dessous):

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] );
    });
2
répondu gotofritz 2012-07-31 09:45:04
var input = ['a', 'b', 'a', 'c', 'c'],
    duplicates = [],
    i, j;
for (i = 0, j = input.length; i < j; i++) {
  if (duplicates.indexOf(input[i]) === -1 && input.indexOf(input[i], i+1) !== -1) {
    duplicates.push(input[i]);
  }
}

console.log(duplicates);
2
répondu Gajus 2013-01-15 22:49:56

je pense que le ci-dessous est la manière la plus facile et la plus rapide O(n) d'accomplir exactement ce que vous avez demandé:

function getDuplicates( arr ) {
  var i, value;
  var all = {};
  var duplicates = [];

  for( i=0; i<arr.length; i++ ) {
    value = arr[i];
    if( all[value] ) {
      duplicates.push( value );
      all[value] = false;
    } else if( typeof all[value] == "undefined" ) {
      all[value] = true;
    }
  }

  return duplicates;
}

ou pour ES5 ou plus:

function getDuplicates( arr ) {
  var all = {};
  return arr.reduce(function( duplicates, value ) {
    if( all[value] ) {
      duplicates.push(value);
      all[value] = false;
    } else if( typeof all[value] == "undefined" ) {
      all[value] = true;
    }
    return duplicates;
  }, []);
}
2
répondu Rafael Xavier 2013-05-23 14:17:23

modifier la solution de @RaphaelMontanaro, en empruntant le blog de @Nosredna, voici ce que vous pouvez faire si vous voulez simplement identifier les éléments dupliqués de votre tableau.

function identifyDuplicatesFromArray(arr) {
        var i;
        var len = arr.length;
        var obj = {};
        var duplicates = [];

        for (i = 0; i < len; i++) {

            if (!obj[arr[i]]) {

                obj[arr[i]] = {};

            }

            else
            {
                duplicates.push(arr[i]);
            }

        }
        return duplicates;
    }

Merci pour la solution élégante, @Nosredna!

2
répondu Bhushan Shah 2014-04-02 07:31:34

Je n'ai pas aimé la plupart des réponses.

pourquoi? Trop compliqué, trop de code, code inefficace et beaucoup ne répondent pas à la question, qui est de trouver les doublons (et de ne pas donner un tableau sans les doublons).

la fonction suivante retourne tous les doublons:

function GetDuplicates(arr) {
  var i, out=[], obj={};
  for (i=0; i < arr.length; i++) 
    obj[arr[i]] == undefined ? obj[arr[i]] ++ : out.push(arr[i]);
  return out;
}  

parce que la plupart du temps, il est inutile de retourner tous les doublons, mais juste pour dire quelles valeurs existent. Dans ce cas, vous retourner un tableau unique avec des doublons ;-)

function GetDuplicates(arr) {
  var i, out=[], obj={};
  for (i=0; i < arr.length; i++)
    obj[arr[i]] == undefined ? obj[arr[i]] ++ : out.push(arr[i]);
  return GetUnique(out);
}

function GetUnique(arr) {
  return $.grep(arr, function(elem, index) {
    return index == $.inArray(elem, arr);
  });
}

Peut-être que quelqu'un d'autre pense la même chose.

2
répondu RWC 2014-05-26 20:36:31

je préfère la fonction façon de faire ceci.

function removeDuplicates(links) {
    return _.reduce(links, function(list, elem) { 
        if (list.indexOf(elem) == -1) {
            list.push(elem);
        }   
        return list;
    }, []);
}

cela utilise un caractère de soulignement, mais le tableau a une reduce fonction, aussi

2
répondu Gras Double 2015-08-02 06:50:10

pour résoudre ce qui précède en O(n) complexité de temps (sans tri).

var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7];

var obj={};

for(var i=0;i<arr.length;i++){
    if(!obj[arr[i]]){
        obj[arr[i]]=1;
    } else {
        obj[arr[i]]=obj[arr[i]]+1;
    }
}
var result=[]
for(var key in obj){
    if(obj[key]>1){
        result.push(Number(key)) // change this to result.push(key) to find duplicate strings in an array
    }
}

console.log(result)
2
répondu Prashant Agrawal 2016-02-06 08:01:54