Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

uniq / sort -u

19 réponses
Avatar
Olivier Miakinen
Bonjour,

Je voudrais savoir s'il existe en JavaScript une fonction standard qui,
à partir d'un tableau de chaînes dont certaines sont présentes plusieurs
fois, n'en garde qu'une ? L'idéal serait que la fonction soit couplée
avec le tri du tableau.

Par exemple, si en entrée j'ai ceci :
{ "fleur", "arbre", "gazon", "fleur", "plante", "fleur", "arbre" }
en sortie j'aurais cela :
{ "arbre", "fleur", "gazon", "plante" }

Je n'ai rien trouvé dans la partie /Array/ de fr.selfhtml.org. Si la
fonction n'existe pas en natif, merci de ne pas passer de temps à me
coder une fonction équivalente : j'utiliserai un autre moyen qui sera
plus rapide qu'un tri avec élimination des doublons.

Cordialement,
--
Olivier Miakinen
Non, monsieur le juge, je vous le jure : jamais je n'ai cité
Bruxelles dans ma signature.

10 réponses

1 2
Avatar
YD

Je voudrais savoir s'il existe en JavaScript une fonction standard qui,
à partir d'un tableau de chaînes dont certaines sont présentes plusieurs
fois, n'en garde qu'une ? L'idéal serait que la fonction soit couplée
avec le tri du tableau.


Ben, non !

Par exemple, si en entrée j'ai ceci :
{ "fleur", "arbre", "gazon", "fleur", "plante", "fleur", "arbre" }
en sortie j'aurais cela :
{ "arbre", "fleur", "gazon", "plante" }

Si la
fonction n'existe pas en natif, merci de ne pas passer de temps à me
coder une fonction équivalente : j'utiliserai un autre moyen qui sera
plus rapide qu'un tri avec élimination des doublons.


C'est ça, tu nous émoustilles les neurones avec enfin autre chose que la
manipulation des formulaires et autres popups... et puis non c'est pas la
peine ! Ceci dit c'est simple 1. on trie, 2. on élimine les doublons et
pour que ça soit plus propre on rajoute ça au prototype de Array. Ce qui
nous donne en quelques lignes (je n'aime pas la longueur...) :

Array.prototype.uniq=function (){
if(!this.length)return;
this.sort();
var a=Array();
a.push(this[0]);
for(i=0; i<this.length-1;)
if(this[i]!=this[++i])
a.push(this[i]);
while(this.length) this.pop();
this.push(a.join());
return this;
}


var a=["fleur", "arbre", "gazon", "fleur", "plante", "fleur", "arbre"];
a.uniq();
alert(a);

NB : si l'Array d'origine ne doit pas être modifiée, remplace les 3
dernières lignes de la fonction par : return a; et l'appel de test
devient alert(a.uniq());

--
Y.D.

Avatar
Olivier Miakinen

C'est ça, tu nous émoustilles les neurones avec enfin autre chose que la
manipulation des formulaires et autres popups... et puis non c'est pas la
peine !


;-)

Ceci dit c'est simple 1. on trie, 2. on élimine les doublons


Oui.

et pour que ça soit plus propre on rajoute ça au prototype de Array.
Ce qui nous donne en quelques lignes (je n'aime pas la longueur...) :

Array.prototype.uniq=function (){ [...] }


Ouaouh ! Mais je ne savais pas que l'on pouvait rajouter des méthodes à
une classe de base ! YD, tu as très bien fait de ne pas tenir compte de
ma demande. Je crois bien que je vais utiliser ta méthode, et peut-être
même pour d'autres choses que cette fonction de tri avec unicité.

Je te devais déjà une bière, mais bientôt ce sera la caisse de vin...

Avatar
YD

Mais je ne savais pas que l'on pouvait rajouter des méthodes à
une classe de base !


Si. Mais on ne peut accéder au prototype de ces objets, comme on peut le
faire avec les objets créés par programmation JS (et pour cause les
méthodes ne sont pas écrites en JS...).

Tu peux aussi redéfinir le temps de ton script une méthode d'un objet
intrinsèque.

Ma solution, rapide, utilisait un tableau auxiliaire en recopiant les
données sans doublons au lieu de travailler directement sur le tableau en
entrée. Je l'ai améliorée en utilisant splice, pour tout faire en une
seule boucle :

Array.prototype.uniq=function (){
if(!this.length)return;
this.sort();
for(i=1; i<this.length;)
if(this[i]==this[i-1])
this.splice(i,1);
else i++;
return this;
}

Je te devais déjà une bière, mais bientôt ce sera la caisse de vin...


Dis moi quand, je t'enverrai mon adresse ;-)

--
Y.D.

Avatar
Cenekemoi
Array.prototype.uniq=function (){
if(!this.length)return;
this.sort();
for(i=1; i<this.length;)
if(this[i]==this[i-1])
this.splice(i,1);
else i++;
return this;
}


Le seul problème avec cet algo (performant) est que l'Array de départ
est modifiée, du coup le "return" se justifie moins et peut même, à la
limite, tromper son monde ! Pour ma part, j'enlèverais cette dernière
ligne...

--
Cordialement, Thierry ;-)

Avatar
YD

Array.prototype.uniq=function (){
if(!this.length)return;
this.sort();
for(i=1; i<this.length;)
if(this[i]==this[i-1])
this.splice(i,1);
else i++;
return this;
}


Le seul problème avec cet algo (performant) est que l'Array de départ
est modifiée, du coup le "return" se justifie moins et peut même, à la
limite, tromper son monde ! Pour ma part, j'enlèverais cette dernière
ligne...


Je m'étais dit la même chose que toi, mais sans cette ligne si on écrit
alert(a.uniq());
on a droit a un beau undefined, même si l'array est bien modifiée... de
même si on veut affecter c=b.concat(a.uniq()); sans le return this il y a
un élément vide inséré dans la table après les éléments de b.

--
Y.D.


Avatar
Cenekemoi

Array.prototype.uniq=function (){
if(!this.length)return;
this.sort();
for(i=1; i<this.length;)
if(this[i]==this[i-1])
this.splice(i,1);
else i++;
return this;
}


Le seul problème avec cet algo (performant) est que l'Array de départ
est modifiée, du coup le "return" se justifie moins et peut même, à
la limite, tromper son monde ! Pour ma part, j'enlèverais cette
dernière ligne...


Je m'étais dit la même chose que toi, mais sans cette ligne si on
écrit alert(a.uniq());
on a droit a un beau undefined, même si l'array est bien modifiée...
de même si on veut affecter c=b.concat(a.uniq()); sans le return this
il y a un élément vide inséré dans la table après les éléments de b.


On est d'accord, c'est pourquoi je préfère ce genre de fonction :

Array.prototype.uniq=function (){
if(!this.length)return;
var b = this.concat();
b.sort();
for(var i=1; i<this.length;)
if(b[i]==b[i-1])
b.splice(i,1);
else i++;
return b;
}

On ne touche pas au tableau de départ et on a notre return


--
Cordialement, Thierry ;-)



Avatar
Cenekemoi
Bonjour à Cenekemoi qui nous

Array.prototype.uniq=function (){
if(!this.length)return;
this.sort();
for(i=1; i<this.length;)
if(this[i]==this[i-1])
this.splice(i,1);
else i++;
return this;
}


Le seul problème avec cet algo (performant) est que l'Array de
départ est modifiée, du coup le "return" se justifie moins et peut
même, à la limite, tromper son monde ! Pour ma part, j'enlèverais
cette dernière ligne...


Je m'étais dit la même chose que toi, mais sans cette ligne si on
écrit alert(a.uniq());
on a droit a un beau undefined, même si l'array est bien modifiée...
de même si on veut affecter c=b.concat(a.uniq()); sans le return this
il y a un élément vide inséré dans la table après les éléments de b.


On est d'accord, c'est pourquoi je préfère ce genre de fonction :

Array.prototype.uniq=function (){
if(!this.length)return;
var b = this.concat();
b.sort();
for(var i=1; i<this.length;)
if(b[i]==b[i-1])
b.splice(i,1);
else i++;
return b;
}

On ne touche pas au tableau de départ et on a notre return


Juste une petite correction au script :

Array.prototype.uniq=function (){
if(!this.length)return [];
var b = this.concat();
b.sort();
for(var i=1; i<b.length;)
if(b[i]==b[i-1])
b.splice(i,1);
else i++;
return b;
}

--
Cordialement, Thierry ;-)




Avatar
Olivier Miakinen
Bonjour,

je reprends ta première réponse.


this.push(a.join());


C'est censé copier le contenu de a dans this ? Ça ne mettrait pas plutôt
dans this un seul élément, qui serait la concaténation des valeurs de a
séparées par des virgules ?

--
Olivier Miakinen
Non, monsieur le juge, je vous le jure : jamais je n'ai cité
Bruxelles dans ma signature.

Avatar
Olivier Miakinen

Array.prototype.uniq=function (){
if(!this.length)return;
this.sort();
for(i=1; i<this.length;)
if(this[i]==this[i-1])
this.splice(i,1);
else i++;
return this;
}


Tout ceci est bel et bon, mais ce code reproduit sous le nom « uniq » le
comportement de la commande shell « sort -u ». En fait, « sort -u » peut
être vu comme l'enchaînement de « sort » suivi par « uniq », ce qui fait
que je verrais plutôt :

Array.prototype.uniq=function (){
for(i=1; i<this.length;)
if(this[i]==this[i-1])
this.splice(i,1);
else i++;
return this;
}

var a=["fleur", "arbre", "gazon", "fleur", "plante", "fleur", "arbre"];
a.sort().uniq();

--
Olivier Miakinen
Non, monsieur le juge, je vous le jure : jamais je n'ai cité
Bruxelles dans ma signature.

Avatar
YD
Tout ceci est bel et bon, mais ce code reproduit sous le nom « uniq » le
comportement de la commande shell « sort -u ». En fait, « sort -u » peut
être vu comme l'enchaînement de « sort » suivi par « uniq », ce qui fait
que je verrais plutôt :

Array.prototype.uniq=function (){
[...]
}

var a=["fleur", "arbre", "gazon", "fleur", "plante", "fleur", "arbre"];
a.sort().uniq();


Attention, si tu enlèves sort() de uniq(), uniq() aura un comportement pas
forcément désiré sur un tableau non trié ! Enfin toi seul connais ton
besoin...

Sinon une fonction uniq() universelle c'est forcément plus lourd (algo qui
va comparer le ième élément avec *tous* ses successeurs et si un (k) lui
est égal --> splice(k,1) jusqu'à la fin de la chaîne, en vite fait :

Array.prototype.uniq=function(){
var i,j;
for(i=0;i<this.length-1;i++)
for(j=i+1;j<this.length;)
if(this[i]==this[j])
this.splice(j,1);
else j++;
return this;
}

--
Y.D.

1 2