J'ai un défi en JavaScript que j'essaie de comprendre depuis un moment déjà.
Considérez ce tableau:
let arr = [0, 1, 0, 2, 0, 3, 0, 4, 0, 5];
Je dois sortir ce résultat:
arr = [0, 0, 0, 0, 0, 5, 4, 3, 2, 1]
Je suis cette ligne de logique pour positionner les zéros devant, en ajustant la valeur d'index:
arr.sort((x, y) => {
if (x !== 0) {
return 1;
}
if (x === 0) {
return -1;
}
return y - x;
});
Mais je suis bloqué sur ce résultat:
arr = [0, 0, 0, 0, 0, 1, 2, 3, 4, 5]
Quelqu'un a-t-il des conseils pour résoudre ce problème?
javascript
arrays
sorting
lianbwl
la source
la source
return x - y;
?return y - x;
? Même en javascript, je ne peux penser à rien qui ne serait ni===0
ni!==0
.Réponses:
Vous pouvez trier par le delta de
b
eta
(pour le tri décroissant) et prendreNumber.MAX_VALUE
, pour des valeurs fausses comme zéro.Cette:
est égal à zéro.
la source
NaN
si les deuxa
etb
sont nuls. Cela peut être un comportement indésirable.Array.prototype.sort
sont définis par l'implémentation si le comparateur revient jamaisNaN
, donc ce comparateur est une mauvaise idée. Il essaie d'être intelligent et se trompe.Comme le dit mdn docs:
Si a et b sont deux éléments comparés, alors:
Ainsi, la fonction de comparaison a la forme suivante:
la source
Si vous vous souciez de l'efficacité, il est probablement plus rapide de filtrer les zéros en premier . Vous ne voulez
sort
pas perdre de temps, même en les regardant, sans parler d'ajouter du travail supplémentaire à votre rappel de comparaison pour gérer ce cas spécial.Surtout si vous vous attendez à un nombre important de zéros, un passage sur les données pour les filtrer devrait être bien mieux que de faire un tri O (N log N) plus grand qui examinera chaque zéro plusieurs fois.
Vous pouvez ajouter efficacement le bon nombre de zéros après avoir terminé.
Il est également tout aussi facile de lire le code résultant. J'ai utilisé TypedArray car il est efficace et facilite le tri numérique . Mais vous pouvez utiliser cette technique avec un tableau standard, en utilisant l'idiome standard de
(a,b)=>a-b
for.sort
.Je ne sais pas si TypedArray
.sort()
puis.reverse
est plus rapide que d'utiliser une fonction de comparaison personnalisée pour trier par ordre décroissant. Ou si nous pouvons copier et inverser à la volée avec un itérateur.À considérer également: n'utilisez qu'un seul TypedArray de toute la longueur .
Au lieu de l'utiliser
.filter
, faites une boucle dessus et permutez les zéros à l'avant du tableau au fur et à mesure. Cela prend un seul passage sur vos données.Ensuite, utilisez
.subarray()
pour obtenir une nouvelle vue TypedArray des éléments non nuls du même ArrayBuffer sous-jacent. Un tri qui vous laissera le tableau complet avec un début zéro et une queue triée, le tri ne regardant que les éléments non nuls.Je n'ai pas vu de fonction de partition dans les méthodes Array ou TypedArray, mais je connais à peine JavaScript. Avec un bon JIT, une boucle ne devrait pas être bien pire qu'une méthode intégrée. (Surtout lorsque cette méthode implique un rappel
.filter
, et à moins qu'elle n'utiliserealloc
sous le capot pour rétrécir, elle doit déterminer la quantité de mémoire à allouer avant qu'elle ne filtre réellement).J'ai utilisé regular-Array
.filter()
avant de convertir en TypedArray. Si votre entrée est déjà un TypedArray, vous n'avez pas ce problème et cette stratégie devient encore plus attrayante.la source
Modifiez simplement l'état de votre fonction de comparaison comme ceci -
la source
!a
est toujours vraie. Il reviendra-1
a=b=0
Ne joue pas au golf de code ici:
la source
N'écrivez pas votre propre tri numérique s'il existe déjà. Ce que vous voulez faire, c'est exactement ce que vous dites dans le titre; trier les nombres dans l'ordre décroissant sauf les zéros au début.
N'écrivez aucun code dont vous n'avez pas besoin; vous pourriez vous tromper.
Choisissez le tableau typé en fonction du type de nombres que vous souhaitez que le tableau gère. Float64 est une bonne valeur par défaut car il gère tous les nombres JS normaux.
la source
Array(n).fill(0)
.let f64arr = new Float64Array(arr.filter(n => n != 0))
, alors[ ...Array(arr.length - f64arr.length).fill(0),
... alors cela ajoute 1 ligne supplémentaire et simplifie la dernière ligne.Vous pouvez faire ceci comme ceci:
ou vous pouvez le faire:
la source
la source