web-dev-qa-db-fra.com

Sorte de tableau javascript et unique

J'ai un tableau JavaScript comme ceci:

var myData=['237','124','255','124','366','255'];

J'ai besoin que les éléments du tableau soient uniques et triés:

myData[0]='124';
myData[1]='237';
myData[2]='255';
myData[3]='366';

Même si les membres de array ressemblent à des entiers , ce sont pas des entiers , puisque j'ai déjà converti chacun en chaîne:

var myData[0]=num.toString();
//...and so on.

Est-il possible de faire toutes ces tâches en JavaScript?

48
theHack

C'est en fait très simple. Il est beaucoup plus facile de trouver des valeurs uniques si les valeurs sont triées en premier:

function sort_unique(arr) {
  if (arr.length === 0) return arr;
  arr = arr.sort(function (a, b) { return a*1 - b*1; });
  var ret = [arr[0]];
  for (var i = 1; i < arr.length; i++) { //Start loop at 1: arr[0] can never be a duplicate
    if (arr[i-1] !== arr[i]) {
      ret.Push(arr[i]);
    }
  }
  return ret;
}
console.log(sort_unique(['237','124','255','124','366','255']));
//["124", "237", "255", "366"]
120
lonesomeday

Cela peut convenir dans des circonstances où vous ne pouvez pas définir la fonction à l’avance (comme dans un bookmarklet):

myData.sort().filter(function(el,i,a){return i===a.indexOf(el)})
31
mrmonkington
function sort_unique(arr) {
    return arr.sort().filter(function(el,i,a) {
        return (i==a.indexOf(el));
    });
}
16
ioleo

Voici mon approche (plus moderne) utilisant Array.protoype.reduce() :

[2, 1, 2, 3].reduce((a, x) => a.includes(x) ? a : [...a, x], []).sort()
// returns [1, 2, 3]

Edit: Version plus performante comme indiqué dans les commentaires:

arr.sort().filter((x, i, a) => !i || x != a[i-1])
13
phaux

Vous pouvez maintenant obtenir le résultat en seulement un ligne de code.

Utilisation de new Set pour réduire le tableau à un ensemble unique de valeurs . Appliquez la méthode sort après pour ordonner les valeurs de chaîne.

var myData=['237','124','255','124','366','255']

var uniqueAndSorted = [...new Set(myData)].sort() 

UPDATED _ pour les méthodes plus récentes introduites dans JavaScript depuis le moment de la question.

10
meteorBuzz

Que diriez-vous:

array.sort().filter(function(elem, index, arr) {
  return index == arr.length - 1 || arr[index + 1] != elem
})

Ceci est similaire à @loostro answer, mais au lieu d'utiliser indexOf qui réitère le tableau pour chaque élément afin de vérifier qu'il est le premier trouvé, il vérifie simplement que l'élément suivant est différent de l'élément actuel.

8
glampr

Essayez d’utiliser une bibliothèque externe comme underscore

var f = _.compose(_.uniq, function(array) {
    return _.sortBy(array, _.identity);
});

var sortedUnique = f(array);

Cela repose sur _.compose , _.uniq , _.sortBy , _.identity

Voir en direct exemple

Qu'est-ce que ça fait?

Nous voulons une fonction qui prend un tableau puis retourne un tableau trié avec les entrées non uniques supprimées. Cette fonction doit faire deux choses, trier et rendre le tableau unique.

C'est un bon travail pour la composition, nous composons donc la fonction unique & sort ensemble. _.uniq peut simplement être appliqué sur le tableau avec un argument, il est donc simplement passé à _.compose

la fonction _.sortBy a besoin d'une fonction de tri conditionnel. il attend une fonction qui retourne une valeur et le tableau sera trié sur cette valeur. Puisque la valeur que nous ordonnons est la valeur du tableau, nous pouvons simplement passer la fonction _.identity. 

Nous avons maintenant une composition de fonction qui (prend un tableau et retourne un tableau unique) et une fonction qui (prend un tableau et retourne un tableau trié, trié par valeur). 

Nous appliquons simplement la composition sur le tableau et nous avons notre tableau trié de manière unique.

6
Raynos

Cette fonction n'échoue pas pour plus de deux valeurs en double:

function unique(arr) {
    var a = [];
    var l = arr.length;
    for(var i=0; i<l; i++) {
        for(var j=i+1; j<l; j++) {
            // If a[i] is found later in the array
            if (arr[i] === arr[j])
              j = ++i;
        }
        a.Push(arr[i]);
    }
    return a;
};
5
Victor

Pas de tableau "retour" redondant, pas d'ECMA5 intégré (j'en suis sûr!) Et simple à lire.

function removeDuplicates(target_array) {
    target_array.sort();
    var i = 0;

    while(i < target_array.length) {
        if(target_array[i] === target_array[i+1]) {
            target_array.splice(i+1,1);
        }
        else {
            i += 1;
        }
    }
    return target_array;
}
1
Amiga500Kid

Une façon d'utiliser une fonction de tri personnalisée

//func has to return 0 in the case in which they are equal
sort_unique = function(arr,func) {
        func = func || function (a, b) {
            return a*1 - b*1;
        };
        arr = arr.sort(func);
        var ret = [arr[0]];
        for (var i = 1; i < arr.length; i++) {
            if (func(arr[i-1],arr[i]) != 0) 
                ret.Push(arr[i]);
            }
        }
        return ret;
    }

Exemple: ordre de desc pour un tableau d'objets

MyArray = sort_unique(MyArray , function(a,b){
            return  b.iterator_internal*1 - a.iterator_internal*1;
        });
1
rodi

Je suppose que je posterai cette réponse pour une variété. Cette technique de suppression des doublons a été choisie pour un projet Flash sur lequel je travaille actuellement il y a environ un mois.

Ce que vous faites est de créer un objet et de le remplir avec une clé et une valeur en utilisant chaque élément du tableau. Étant donné que les clés en double sont supprimées, les doublons sont supprimés.

var nums = [1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10];
var newNums = purgeArray(nums);

function purgeArray(ar)
{
    var obj = {};
    var temp = [];
    for(var i=0;i<ar.length;i++)
    {
        obj[ar[i]] = ar[i];
    }
    for (var item in obj)
    {
        temp.Push(obj[item]);
    }
    return temp;
}

Il y a déjà 5 autres réponses, donc je ne vois pas la nécessité de poster une fonction de tri.

0
user1385191

Les solutions O [N ^ 2] sont mauvaises, en particulier lorsque les données sont déjà triées, il n'est pas nécessaire de créer deux boucles imbriquées pour supprimer les doublons. Une boucle et comparer à l'élément précédent fonctionnera très bien.

Une solution simple avec O [] de sort () suffirait. Ma solution est:

function sortUnique(arr, compareFunction) {
  let sorted = arr.sort(compareFunction);
  let result = sorted.filter(compareFunction
    ? function(val, i, a) { return (i == 0 || compareFunction(a[i-1], val) != 0); }
    : function(val, i, a) { return (i == 0 || a[i-1] !== val); }
  );
  return result;
}

BTW, peut faire quelque chose comme ceci pour avoir la méthode Array.sortUnique ():

Array.prototype.sortUnique = function(compareFunction) {return sortUnique(this, compareFunction); }

En outre, sort () pourrait être modifié pour supprimer le deuxième élément si la fonction compare () renvoie 0 (éléments égaux), bien que ce code puisse devenir compliqué (nécessité de réviser les limites de la boucle dans le vol). De plus, je me garde de faire mes propres fonctions sort () dans les langages interprétés, car cela dégraderait très certainement les performances. Donc, cet ajout est pour la considération ECMA 2019+.

0
iva2k

Voici un simple liner avec O(N), en supposant que:

  • vous êtes dans un navigateur moderne ou dans node.js
  • votre tableau est des chaînes

Ensuite

> Object.keys([{}].concat(['a', 'b', 'a']).reduce((l,r) => l[r] = l ))
[ 'a', 'b' ]

Explication

Jeu de données d'origine, supposons qu'il vienne d'une fonction externe

let data = ['a', 'b', 'a']

Nous voulons ajouter un objet devant le tableau

let setup = [{}].concat(data)

Ensuite, nous voulons réduire le tableau en une seule valeur.

Dans l'étape précédente, nous avons ajouté l'objet au tableau afin que nous puissions coller toutes les valeurs sur cet objet, en tant que clés, dans cette étape. Le résultat final est un objet avec un ensemble unique de clés.

let reduced = setup.reduce((l,r) => l[r] = l)

Nous définissons l[r] = l car en javascript, la valeur de l'expression d'affectation est renvoyée lorsqu'une instruction d'affectation est utilisée comme expression.

Ensuite, nous voulons obtenir les clés de cet objet

let keys = Object.keys(setup)

Quel est l'ensemble des valeurs uniques du tableau d'origine

['a', 'b']
0
justin.m.chase

function sort () seulement n'est valable que si votre numéro a le même chiffre, exemple:

var myData = ["3","11","1","2"]

reviendrai

var myData = ["1","11","2","3"]

et ici l'amélioration de la fonction de mrmonkington

myData.sort().sort(function(a,b){return a - b;}).filter(function(el,i,a){if(i==a.indexOf(el) & el.length>0)return 1;return 0;})

la fonction ci-dessus supprimera également le tableau vide et vous pourrez vérifier la démo ci-dessous

http://jsbin.com/ahojip/2/edit
0
ewwink
// Another way, that does not rearrange the original Array 
// and spends a little less time handling duplicates.

function uniqueSort(arr, sortby){
    var A1= arr.slice();
    A1= typeof sortby== 'function'? A1.sort(sortby): A1.sort();

    var last= A1.shift(), next, A2= [last];
    while(A1.length){
        next= A1.shift();
        while(next=== last) next= A1.shift();
        if(next!=undefined){
            A2[A2.length]= next;
            last= next;
        }
    }
    return A2;
}
var myData= ['237','124','255','124','366','255','100','1000'];
uniqueSort(myData,function(a,b){return a-b})

// the ordinary sort() returns the same array as the number sort here,
// but some strings of digits do not sort so nicely numerical.
0
kennebec