Sortowanie tablicy obiektów wg. wartości undefined i false

1

Witam,
mam mały problem - mianowicie mam tablicę obiektów, które mają propety isActive mogące przyjąć wartość false/undefined. Potrzebuję posortować moją tablicę, w kolejności undefined -> false (np. [undefined, false, false, undefined] -> [undefined, undefined, false, false]). Jak porównywać te 2 wartości?

1

Ogólnie funkcja sort przyjmuje callback, który pozwoli ci porównać:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
wydaje się łatwe. Teoretycznie wystarczyłoby porównać coś z undefined i jeśli tak, to stwierdzić, że coś jest mniejsze/większe zwracając 1 albo -1. Teoretycznie.

Jednak z jakiegoś powodu JS traktuje undefined inaczej niż inne wartości przy sortowaniu. Taki kawałek kodu próbowałem:

const VALUE = undefined;
const arr = [10, 30, 89, 2, VALUE, 3, VALUE];
arr.sort((a, b) => {
	if (a === VALUE) {
		return -1;
	}
	if (b === VALUE) {
		return 1;
	}	
	return a - b;
})
console.log(arr);

I teraz, co ciekawe, jeśli za VALUE podstawimy coś innego, np.

const VALUE = 'foo'; // albo np. const VALUE = null;

to wyjdzie nam ta wartość na początku:

['foo', 'foo', 2, 3, 10, 30,  89]
[null, null, 2, 3, 10, 30, 89]

przy undefined mamy inaczej:

const VALUE = undefined;

dałoby

[ 2, 3, 10, 30, 89, undefined, undefined ]

W sumie niezły WTF, chociaż opisany przez MDN:

all undefined elements are sorted to the end of the array, with no call to compareFunction).

Czyli język JS nie pozwala bezpośrednio na to, co chcesz zrobić, choć możesz to jakoś spróbować obejść, np. po sortowaniu zabrać undefined z końca i wstawić na początek. Albo zamiast undefined używać null itp.

2

Najprostsze rozwiązanie na metodę sort jakie przychodzi mi do głowy to użycie reverse :D

const values = [undefined, false, undefined, false, true, true, false];

const sortA = [...values].sort((a, b) => b - a);            
const sortB = [...values].sort((a, b) => b - a).reverse();

console.dir(sortA); // true, true, false, false, false, undefined, undefined
console.dir(sortB); // undefined, undefined, false, false, false, true, true

Można też spróbować napisać własny algorytm do sortowania, który nie ma tego problemu.

2
const f = { isActive: false }
const u = { isActive: undefined };

const list = [
  {...u, id: 1},
  {...f, id: 2},
  {...f, id: 3},
  {...u, id: 4},
];

// ^ przygotowanie danych

// -----

// v implementacja rozwiązania

list.sort(s => s.isActive === undefined ? -1 : 1);

console.log(list)

Najprościej tak

0
LukeJL napisał(a):

Czyli język JS nie pozwala bezpośrednio na to, co chcesz zrobić, choć możesz to jakoś spróbować obejść, np. po sortowaniu zabrać undefined z końca i wstawić na początek. Albo zamiast undefined używać null itp.

Nie zaraz język, tylko funkcja w bibliotece standardowej. Nie wprowadzaj w błąd.

0
LukeJL napisał(a):

Ale to cześć języka. AFAIK. Bo można się przejechać. Np. console.log nie jest częścią JSa. Ale tablice i ich metody to (o ile dobrze wiem) cześć specyfikacji EcmaScript wiec cześć JSa dla mnie.

Ale mówić Czyli język JS nie pozwala bezpośrednio na to, co chcesz zrobić to nie prawda, bo możesz w tym języku napisać sobie .sort() jaki tylko chcesz, a potem wsadzić to w Array.prototype.sort jak chcesz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1