#javascript #arrays #performance #sorting #comparison
Вопрос:
Ввод:
[7,"a","b",5, 0.1, "c", 0.5, 9, 1, "e", "m", 0.3, 8.5, 74, 89,"f","r",0.5 ,"x", "y", 4, 7]
Выход:
["a", "b", "c", "e", "m", "f", "r", "x", "y", 0.1, 0.5, 0.3, 8.5, 0.5, 7, 5, 9, 1, 74, 89, 4, 7]
function sorter(arr) {
var arr1, arr2, arr3;
arr1 = [];
arr2 = [];
arr3 = [];
for (var i = 0; i < arr.length; i ) {
if (typeof arr[i] === "string") {
arr1.push(arr[i]);
} else if (typeof arr[i] === 'number' amp;amp; !isNaN(arr[i])) {
if (Number.isInteger(arr[i])) {
arr3.push(arr[i]);
} else {
arr2.push(arr[i]);
}
}
}
return [...arr1, ...arr2, ...arr3];
}
Комментарии:
1. Вы хотите отредактировать функцию компаратора сортировки? Что происходит, когда вы запускаете свой текущий код
2. Использование массивов смешанного типа, подобных этому, вероятно, является проблемой xy для начала. Вы уверены , что вам нужны данные в этой форме, и нет лучшего представления? До тех пор, пока вы сохраняете данные в этой форме, ваши алгоритмы для работы с ними будут неудобными, с множеством ветвей для проверки типов повсюду.
3. Я добавил выходные данные для своего текущего кода. Просто я хочу оптимизировать свою функцию сортировки, не используя никаких дополнительных массивов.
4. Сначала в JS нет смысла указывать «целые числа», потому что в JS нет целых чисел. «12.0» и «12» — это точно одно и то же число, так что бы произошло, если бы ваш ввод был
[11, 12.0, 12]
?5. @Анкита … Существует бережливый подход, основанный на обратном вызове одного компаратора сортировки
Ответ №1:
Используйте sort()
метод с функцией сравнения, которая сравнивает типы, а не значения.
function sorter(arr) {
function type_index(val) {
const types = ["string", "float", "integer"];
let type;
if (typeof val == "string") {
type = "string";
} else if (typeof val == "number" amp;amp; Number.isInteger(val)) {
type = "integer";
} else if (typeof val == "number" amp;amp; !isNaN(val)) {
type = "float";
}
return types.indexOf(type);
}
return arr.sort((a, b) => type_index(a) - type_index(b));
}
console.log(sorter([7,"a","b",5, 0.1, "c", 0.5, 9, 1, "e", "m", 0.3, 8.5, 74, 89,"f","r",0.5 ,"x", "y", 4, 7]));
Ответ №2:
Подход, основанный на одном sort
обратном вызове компаратора …
function orderByItemTypeOnly(a, b) {
const precedences = {
'string': 1,
'float': 2,
'int': 3,
};
const getType = val =>
((typeof val === 'number') amp;amp; Number.isFinite(val))
? Number.isInteger(val) amp;amp; 'int' || 'float'
: (typeof val);
const aType = getType(a);
const bType = getType(b);
return (
(precedences[aType] || 4) - (precedences[bType] || 4)
);
}
console.log([
7, "a", "b", 5, 0.1, "c", 0.5, 9, 1, "e", "m",
0.3, 8.5, 74, 89, "f", "r", 0.5, "x", "y", 4, 7
].sort(orderByItemTypeOnly));
.as-console-wrapper { min-height: 100%!important; top: 0; }
Существует также возможность решения этой задачи не с помощью sort
, а на основе reduce
подхода …
function collectAndShiftItemByType(list, item, idx, arr) {
if (list.length === 0) {
list.push([], [], [], []);
}
const typeListIndex = ((typeof item === 'number') amp;amp; Number.isFinite(item))
? (Number.isInteger(item) amp;amp; 2 || 1)
: (typeof item === 'string') ? 0 : 3;
// push into sub lists ... [0]string, [1]float, [2]integer, [3]unknown.
list[typeListIndex].push(item);
if (idx >= arr.length - 1) {
list = list[0]
.concat(list[1])
.concat(list[2])
.concat(list[3]);
}
return list;
}
console.log([
7, "a", "b", 5, 0.1, "c", 0.5, 9, 1, "e", "m",
0.3, 8.5, 74, 89, "f", "r", 0.5, "x", "y", 4, 7
].reduce(collectAndShiftItemByType, []));
.as-console-wrapper { min-height: 100%!important; top: 0; }