Сортировка массива по интервалам
Столкнулся со следующей проблемой. По какой логике должен работать фильтр, чтобы отсортировать интервалы в порядке возрастания сравнивая промежутки интервалов? null считается за бесконечность Получается, что вывести должно [0,100] [100,200] [50,250] [56,324] [null,400] [200,null] [500,null] [null,null] Данный метод изначально выводит правильные интервалы, но под конец начинает вести себя странно и сортирует неверно. Подскажите в чем ошибка? И как мне отсортировать массив по интервалам?
let homes = [
{ prices: [0, 100] },
{ prices: [500, null] },
{ prices: [100, 200] },
{ prices: [null, 400] },
{ prices: [50, 250] },
{ prices: [200, null] },
{ prices: [56, 324] },
{ prices: [null, null] },
];
let filter = homes.sort(function(a, b) {
return parseFloat(a.prices) - parseFloat(b.prices);
});
console.log(filter);
Ответы (3 шт):
Проблема в том что значение может быть null. Вы этот момент игнорируете. Посмотрите на результат парсинга null
console.log(parseFloat(null)); // NaN
console.log(parseFloat(null)-parseFloat(100)) //NaN
Вам надо эти null както-то интерпретировать - первый null в кортеже это минимальное число (аналог "минус бесконечность"), а null на втором месте в кортеже - "плюс бесконечность" (максимальное число) . Плюс к этому вам надо вычислить длину интервала в кортеже. Если я правильно понял вашу задачу, получится что-то такое
let homes = [
{ prices: [0, 100] },
{ prices: [500, null] },
{ prices: [100, 200] },
{ prices: [null, 400] },
{ prices: [50, 250] },
{ prices: [200, null] },
{ prices: [56, 324] },
{ prices: [null, null] },
];
let filter = homes.sort(function(a, b) {
range_a = Math.abs(parseFloat(a.prices[1]==null?Number.MAX_VALUE:a.prices[1]) - parseFloat(a.prices[0]==null?Number.MIN_VALUE:a.prices[0]));
range_b = Math.abs(parseFloat(b.prices[1]==null?Number.MAX_VALUE:b.prices[1]) - parseFloat(b.prices[0]==null?Number.MIN_VALUE:b.prices[0]));
return range_a-range_b;
});
console.log(filter);
Я так понял, null - это +-бесконечность. Соответственно, самым большим интервалом будет [Number.MIN_VALUE, Number.MAX_VALUE].
Учитывая это, должно получиться что-то такое:
let homes = [
{ prices: [0, 100] },
{ prices: [500, null] },
{ prices: [100, 200] },
{ prices: [null, 400] },
{ prices: [50, 250] },
{ prices: [200, null] },
{ prices: [56, 324] },
{ prices: [null, null] },
];
let filter = homes.sort(function(a, b) {
if (!a.prices[1] && !a.prices[1]) return 1;
const intA = a.prices[1]?a.prices[1]:Number.MAX_VALUE - a.prices[0]?a.prices[0]:Number.MIN_VALUE;
const intB = b.prices[1]?b.prices[1]:Number.MAX_VALUE - b.prices[0]?b.prices[0]:Number.MIN_VALUE;
return intA - intB;
});
console.log(filter);
Можно представить что левый null - это 0, а правый - это Infinity. Тогда мы можем получить длину диапазонов вычислением разницы правой и левой границы
Остаётся случай, когда у двух и более диапазонов правая граница может быть бесконечностью, тогда длина их всех будет равна бесконечности т.к. если от бесконечности отнять любое число, то ответ будет бесконечность. Решаем эту проблему значением левой границы. Чем она меньше тем длина диапазона длиннее, в случае, когда справа бесконечность
Ну и собственно сам код:
const homes = [
{ prices: [0, 100] },
{ prices: [500, null] },
{ prices: [100, 200] },
{ prices: [null, 400] },
{ prices: [50, 250] },
{ prices: [200, null] },
{ prices: [56, 324] },
{ prices: [null, null] },
];
const getRangeLength = (range) => (range[1] || Infinity) - (range[0] || 0);
homes.sort((home1, home2) => {
const home1Prices = home1.prices;
const home2Prices = home2.prices;
const home1PricesRangeLength = getRangeLength(home1.prices);
const home2PricesRangeLength = getRangeLength(home2.prices);
if (home1PricesRangeLength === Infinity && home2PricesRangeLength === Infinity) {
return home2Prices[0] - home1Prices[0];
}
return home1PricesRangeLength - home2PricesRangeLength;
});
console.log(homes.map(x => x.prices));