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.

9 réponses

1 2
Avatar
YD

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 (){
[...]
return b;
}

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



Ce n'est pas le comportement de la plupart des fonctions du prototype
d'Array : sort() renvoie le tableau trié *et* le modifie, de même pour
reverse()... Mais c'est un choix de conception.


Juste une petite correction au script :

Array.prototype.uniq=function (){
if(!this.length)return [];
(J'avais zappé aussi ce return !)

[...]
}


--
Y.D.




Avatar
YD
Bonjour,

je reprends ta première réponse.



this.push(a.join());



C'est censé copier le contenu de a dans this ?


Oui, puisqu'on ne peut pas affecter à 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 ?


Oooooooops !

Remplacer par (pas trouvé moyen de faire ça d'un coup :-( ) :
while(a.length)this.push(a.shift());

--
Y.D.


Avatar
Olivier Miakinen

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...


C'est peut-être un comportement qui peut sembler curieux, mais
c'est bien celui de la commande standard 'uniq' :
http://unixhelp.ed.ac.uk/CGI/man-cgi?uniq

L'équivalent de 'sort' + 'uniq', c'est 'sort -u' :
http://unixhelp.ed.ac.uk/CGI/man-cgi?sort

L'avantage de séparer les deux, c'est que si tu sais que le tableau est
déjà trié tu n'as pas besoin de perdre du temps à le faire. Du coup, le
comportement n'est pas si bizarre que ça : soit tu sais que le tableau
est trié et tu utilises uniq() directement, soit tu n'en sais rien et tu
le tries d'abord.

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


Ok, mais alors il ne faut pas l'appeler uniq s'il existe une chance sur
un million qu'un utilisateur Unix tombe dessus.

Avatar
YD

C'est peut-être un comportement qui peut sembler curieux, mais
c'est bien celui de la commande standard 'uniq' :
http://unixhelp.ed.ac.uk/CGI/man-cgi?uniq

L'équivalent de 'sort' + 'uniq', c'est 'sort -u' :
http://unixhelp.ed.ac.uk/CGI/man-cgi?sort

L'avantage de séparer les deux, c'est que si tu sais que le tableau est
déjà trié tu n'as pas besoin de perdre du temps à le faire. Du coup, le
comportement n'est pas si bizarre que ça : soit tu sais que le tableau
est trié et tu utilises uniq() directement, soit tu n'en sais rien et tu
le tries d'abord.


J'ai appris une commande nix ce soir -- et qui a un beau paquet d'options...

--
Y.D.

Avatar
Cenekemoi
Ce n'est pas le comportement de la plupart des fonctions du prototype
d'Array : sort() renvoie le tableau trié *et* le modifie, de même pour
reverse()...


Mea culpa, je n'avais pas fait attention à ce détail (qui n'en est pas
un) ! Je retiendrais ce point...

... Mais c'est un choix de conception.


toutafé ;-)

--
Cordialement, Thierry

Avatar
Cenekemoi
this.push(a.join());
C'est censé copier le contenu de a dans this ?




Pour copier une array "a" dans une autre "b" :

var b = a.concat();

(simple, précis, pas très clair)

(...)
Remplacer par (pas trouvé moyen de faire ça d'un coup :-( ) :
while(a.length)this.push(a.shift());


un peu lourd, non ?

--
Cordialement, Thierry ;-)



Avatar
YD



this.push(a.join());


C'est censé copier le contenu de a dans this ?




Pour copier une array "a" dans une autre "b" :

var b = a.concat();

(simple, précis, pas très clair)


Très simple, mais on n'a pas le droit d'affecter à this,
(sinon je me serais contenté de this=a...) !

--
Y.D.




Avatar
Cenekemoi
Pour copier une array "a" dans une autre "b" :

var b = a.concat();

(simple, précis, pas très clair)


Très simple, mais on n'a pas le droit d'affecter à this,
(sinon je me serais contenté de this=a...) !


Attention à ta dernière phrase : "this=a" ne représente pas du tout la
même chose :

[1] var b = a.concat(); ==> COPIE a dans b
[2] var b = a; ==> affecte la REFERENCE de a dans b

En d'autres termes, avec [1] j'ai bien DEUX objets, tandis qu'avec [2]
j'ai deux références vers UN SEUL objet. Il suffit de modifier "b" pour
s'apercevoir que "a" aussi est modifié dans ce dernier cas et pas dans
le premier...

--
Cordialement, Thierry ;-)


Avatar
YD

Très simple, mais on n'a pas le droit d'affecter à this,
(sinon je me serais contenté de this=a...) !



Attention à ta dernière phrase : "this=a" ne représente pas du tout la
même chose :

[1] var b = a.concat(); ==> COPIE a dans b
[2] var b = a; ==> affecte la REFERENCE de a dans b

En d'autres termes, avec [1] j'ai bien DEUX objets, tandis qu'avec [2]
j'ai deux références vers UN SEUL objet. Il suffit de modifier "b" pour
s'apercevoir que "a" aussi est modifié dans ce dernier cas et pas dans
le premier...


Entièrement d'accord, mais en l'occurrence a est une variable qui n'a
d'existence que le temps d'exécution de la fonction et this = a affecterait
(si c'était possible) la même référence qui n'existerait plus que pour
l'objet désigné par this après l'exécution de la fonction. C'est vrai que
pour le coup j'ai été un peu rapide et il est toujours bon de rappeler qu'en
javascript l'affectation des objets se fait par référence et que, hormis les
valeurs primitives (nombres, chaînes, null, true false) tout est objet.

Désolé pour ce fil, décousu pour cause de vacances ;-)

--
Y.D.


1 2