У меня есть проблема в JavaScript, которую я пытаюсь решить уже некоторое время.
Рассмотрим этот массив:
let arr = [0, 1, 0, 2, 0, 3, 0, 4, 0, 5];
Я должен вывести этот результат:
arr = [0, 0, 0, 0, 0, 5, 4, 3, 2, 1]
Я следую этой строке логики, чтобы расположить нули впереди, регулируя значение индекса:
arr.sort((x, y) => {
if (x !== 0) {
return 1;
}
if (x === 0) {
return -1;
}
return y - x;
});
Но я застрял в этом результате:
arr = [0, 0, 0, 0, 0, 1, 2, 3, 4, 5]
У кого-нибудь есть какие-нибудь советы, как это решить?
javascript
arrays
sorting
lianbwl
источник
источник
return x - y;
?return y - x;
? Даже в javascript я не могу думать ни о чем, что было бы ни то,===0
ни другое!==0
.Ответы:
Вы можете отсортировать по дельте
b
иa
(для сортировки по убыванию) и принятьNumber.MAX_VALUE
для ложных значений, таких как ноль.Эта:
равно нулю.
источник
NaN
если обаa
иb
равны нулю. Это может быть нежелательным поведением.Array.prototype.sort
определяются реализацией, если компаратор когда-либо возвращаетсяNaN
, поэтому этот компаратор - плохая идея. Он пытается быть умным и ошибается.Как сказано в MDN Docs:
Если a и b - два сравниваемых элемента, то:
Итак, функция сравнения имеет следующий вид:
источник
Если вы заботитесь об эффективности, возможно, быстрее всего сначала отфильтровать нули . Вы не хотите
sort
тратить время, даже глядя на них, не говоря уже о добавлении дополнительной работы к вашему обратному вызову сравнения для обработки этого особого случая.Особенно, если вы ожидаете значительное количество нулей, один проход по данным для их фильтрации должен быть намного лучше, чем выполнять более крупную O (N log N) сортировку, которая будет смотреть на каждый ноль несколько раз.
Вы можете эффективно добавлять правильное количество нулей после того, как вы закончите.
Также легко прочитать полученный код. Я использовал TypedArray, потому что он эффективен и упрощает сортировку чисел . Но вы можете использовать эту технику с обычным массивом, используя стандартную идиому
(a,b)=>a-b
для.sort
.Я не знаю, если TypedArray,
.sort()
а затем.reverse
быстрее, чем с помощью пользовательской функции сравнения для сортировки в порядке убывания. Или, если мы можем копировать и обратно на лету с итератором.Также стоит подумать: используйте только один TypedArray полной длины .
Вместо того, чтобы использовать
.filter
, зациклите его и поменяйте местами нули в начале массива. Это займет один проход над вашими данными.Затем используйте
.subarray()
для получения нового представления TypedArray ненулевых элементов того же базового ArrayBuffer. Сортировка, в результате которой вы получите полный массив с нулевым началом и отсортированным хвостом, причем сортировка всегда будет рассматривать только ненулевые элементы.Я не видел функции разделения в методах Array или TypedArray, но я почти не знаю JavaScript. При хорошем JIT цикл не должен быть намного хуже, чем встроенный метод. (Особенно, когда этот метод включает в себя функцию обратного вызова
.filter
, и если он не используетсяrealloc
под капотом для сжатия, он должен выяснить, сколько памяти выделить, прежде чем он фактически отфильтровывается).Я использовал обычный массив
.filter()
перед преобразованием в TypedArray. Если ваши входные данные уже являются TypedArray, у вас нет этой проблемы, и эта стратегия становится еще более привлекательной.источник
Просто измените условие вашей функции сравнения следующим образом:
источник
!a
все еще выполняется. Это вернется-1
a=b=0
Не играю в гольф-код здесь:
источник
Не пишите свою собственную числовую сортировку, если она уже существует. То, что вы хотите сделать, это именно то, что вы говорите в названии; сортировать числа в порядке убывания, кроме нулей в начале.
Не пишите код, который вам не нужен; Вы можете ошибаться.
Выберите TypedArray в зависимости от того, какой тип чисел вы хотите обработать. Float64 является хорошим значением по умолчанию, поскольку он обрабатывает все обычные числа JS.
источник
Array(n).fill(0)
.let f64arr = new Float64Array(arr.filter(n => n != 0))
, то[ ...Array(arr.length - f64arr.length).fill(0),
... так что это добавляет 1 дополнительную строку и упрощает последнюю строку.Вы можете сделать это так:
или вы можете сделать это:
источник
источник