Jeśli zależy Ci na wydajności, prawdopodobnie najszybciej odfiltruje zera . Nie chcesz sorttracić czasu, nawet na nie patrząc, nie mówiąc już o dodaniu dodatkowej pracy do wywołania zwrotnego porównania w celu obsługi tego specjalnego przypadku.
Zwłaszcza jeśli spodziewasz się znacznej liczby zer, jedno przejście przez dane w celu ich odfiltrowania powinno być znacznie lepsze niż wykonanie większego sortowania O (N log N), który będzie sprawdzał każde zera wiele razy.
Po zakończeniu możesz skutecznie wstawić poprawną liczbę zer.
Równie łatwo jest odczytać wynikowy kod. Użyłem TypedArray, ponieważ jest wydajny i ułatwia sortowanie numeryczne . Ale możesz użyć tej techniki ze zwykłym Array, używając standardowego idiomu (a,b)=>a-bfor .sort.
let arr = [0, 1, 0, 2, 0, 3, 0, 4, 0, 5];
let nonzero_arr = Int32Array.from(arr.filter(n => n != 0));
let zcount = arr.length - nonzero_arr.length;
nonzero_arr.sort(); // numeric TypedArray sorts numerically, not alphabetically
// Reverse the sorted part before copying into the final array.
nonzero_arr.reverse();
// efficient-ish TypedArray for main result
let revsorted = new Int32Array(arr.length); // zero-filled full size
revsorted.set(nonzero_arr, zcount); // copy after the right number of zeros
console.log(Array.from(revsorted)); // prints strangely for TypedArray, with invented "0", "1" keys
/*
// regular Array result
let sorted = [...Array(zcount).fill(0), ...nonzero_arr] // IDK if this is efficient
console.log(sorted);
*/
Nie wiem, czy TypedArray, .sort()a następnie .reversejest szybszy niż używanie niestandardowej funkcji porównywania do sortowania w kolejności malejącej. Lub jeśli możemy kopiować i cofać w locie za pomocą iteratora.
Warto również rozważyć: użyj tylko jednego Tablicy Typów o pełnej długości .
Zamiast tego użyj .filterpętli i zamień zera na przód tablicy podczas pracy. To zajmuje jedno przejście przez twoje dane.
Następnie użyj .subarray() aby uzyskać nowy widok TypedArray niezerowych elementów tego samego bazowego ArrayBuffer. Sortowanie, które pozostawia pełną tablicę z zerowym początkiem i posortowanym ogonem, przy czym sortowanie obejmuje tylko niezerowe elementy.
Nie widziałem funkcji partycji w metodach Array ani TypedArray, ale ledwo znam JavaScript. Przy dobrym JIT pętla nie powinna być o wiele gorsza niż wbudowana metoda. (Zwłaszcza gdy ta metoda wymaga wywołania zwrotnego.filter , i jeśli nie używa się reallocpod maską do zmniejszenia, musi dowiedzieć się, ile pamięci do przydzielenia, zanim faktycznie się odfiltruje).
Użyłem tablicy regularnej .filter() przed konwersją na tablicę TypedArray. Jeśli Twój wkład jest już TypedArray, nie masz tego problemu, a ta strategia staje się jeszcze bardziej atrakcyjna.