Якщо ви піклуєтесь про ефективність, напевно, найшвидше спочатку відфільтрувати нулі . Ви не хочете sort
витрачати час, навіть не дивлячись на них, не кажучи вже про додавання додаткової роботи до зворотного виклику порівняння, щоб обробити цей особливий випадок.
Особливо, якщо ви очікуєте значної кількості нулів, один пропуск даних для їх фільтрації повинен бути набагато кращим, ніж робити великий розмір O (N log N), який буде дивитися на кожен нуль кілька разів.
Ви можете ефективно додати потрібну кількість нулів, коли закінчите.
Так само просто читати отриманий код. Я використовував TypedArray, тому що він ефективний і полегшує числове сортування . Але ви можете використовувати цю техніку за допомогою звичайного масиву, використовуючи стандартну ідіому (a,b)=>a-b
для .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);
*/
Я не знаю, чи TypedArray, .sort()
а потім .reverse
швидше, ніж використання спеціальної функції порівняння для сортування у порядку зменшення. Або якщо ми можемо копіювати і повертати назад на льоту за допомогою ітератора.
Також варто врахувати: використовувати тільки один TypedArray повної довжини .
Замість використання .filter
переведіть на нього цикл і поміняйте нулі на передню частину масиву, як ви йдете. Це займе один пропуск над вашими даними.
Потім використовуйте .subarray()
для отримання нового виду TypedArray ненульових елементів того ж базового ArrayBuffer. Сортування, яке залишить вам повний масив із нульовим початком та відсортованим хвостом, з сортуванням, що коли-небудь дивиться на ненульові елементи.
Я не бачив функції розділу в методах Array або TypedArray, але я ледве знаю JavaScript. При хорошому JIT цикл не повинен бути надто гіршим, ніж вбудований метод. (Особливо, коли цей метод включає в себе зворотний виклик .filter
, і якщо він не використовується realloc
під кришкою для зменшення, він повинен з'ясувати, скільки пам'яті потрібно виділити до того, як вона насправді фільтрує).
.filter()
Перед перетворенням в TypedArray я використовував regular-Array . Якщо ваш внесок вже є TypedArray, у вас немає цієї проблеми, і ця стратегія стає ще більш привабливою.