Mundarija (34)
- Bu darsda
- 1. Nega bu kerak?
- 2. Standart sort: hamma narsa satr
- 2.1 Satrlarda ishlaydi
- 2.2 Sonlarda — tuzoq
- 2.3 Nega shunday qilingan?
- 3. Taqqoslash funksiyasi
- 3.1 (a, b) => a - b
- 3.2 Qaytgan son nimani bildiradi
- 3.3 sort ichidan
- 3.4 Kim kim bilan solishtiriladi?
- 4. Obyektlarni saralash
- 4.1 Bitta kalit bo'yicha
- 4.2 Bir necha kalit bo'yicha
- 4.3 Barqaror saralash
- 5. Matnni to'g'ri saralash: localeCompare
- 5.1 Katta-kichik harf
- 5.2 O'zbek harflari
- 5.3 Brauzerda boshqacha!
- 5.4 Intl.Collator — tayyor taqqoslash funksiyasi
- 6. sort asl massivni o'zgartiradi
- 7. Ko'p uchraydigan xatolar
- 7.1 Sonlarni taqqoslash funksiyasisiz saralash
- 7.2 Taqqoslash funksiyasi true/false qaytaradi
- 7.3 Satrlarni ayirish
- 7.4 Saralangan nusxa o'rniga aslini o'zgartirish
- 8. Mashqlar
- 1-mashq (oson): Imtihon natijalari
- 2-mashq (o'rta): Taksi haydovchilari
- 3-mashq (qiyin): Brauzer uchun o'zbekcha tartib
- 4-mashq: Vazifalar qadami — bajarilmaganlar tepada
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript sort metodi: massivni saralash va taqqoslash funksiyasi
Qisqacha:
sortmassivni joyida saralaydi. Taqqoslash funksiyasisiz u har elementni satrga aylantirib solishtiradi, shuning uchun[10, 9, 1].sort()—[1, 10, 9]. Sonlar uchun funksiya bering:narxlar.sort((a, b) => a - b). Matnlar uchun —a.localeCompare(b, "uz"). Esda tuting:sortasl massivni o'zgartiradi.
Bu darsda
- Nega
sortsonlarni "noto'g'ri" tartiblashini tushuntira olasiz. - Taqqoslash funksiyasini (
(a, b) => a - b) yozib, sonlarni o'sish va kamayish tartibida saralay olasiz. - Obyektlarni bir yoki bir necha kalit bo'yicha saralay olasiz va barqaror saralash nima ekanini bilasiz.
localeComparevaIntl.Collatorbilan o'zbekcha so'zlarni saralay olasiz — va brauzerdagi tuzog'ini bilasiz.vazifalarda bajarilmagan vazifalarni ro'yxat tepasiga chiqarasiz.
Oldin bilishingiz kerak: Callback imzosi va HOF metodlari, reduce, Taqqoslash operatorlari, Element qo'shish va olib tashlash, Havola semantikasi.
1. Nega bu kerak?
Jasur aka «Bahor» devoridagi menyu taxtasini yangilamoqchi: taomlar arzonidan qimmatiga qarab tursin. Narxlar massivda bor, massivda esa sort ("saralamoq") metodi bor. Sinab ko'ramiz:
const narxlar = [35000, 28000, 5000, 30000];
narxlar.sort();
console.log(narxlar); // [ 28000, 30000, 35000, 5000 ]Ko'k choy (5 000 so'm) eng qimmat bo'lib qoldi! Xato xabari yo'q, dastur ishladi. Lekin natija noto'g'ri.
Taqqoslash operatorlari darsida bunga o'xshash tuzoqni ko'rgan edik: "10" < "9" — true. O'sha darsda yana bir va'da bergan edik: o'zbekcha so'zlarni alifbo bo'yicha to'g'ri saralash usulini shu darsda ko'rsatamiz. Bugun ikkala masalani ham hal qilamiz.
Hayotdan o'xshatish. Jismoniy tarbiya o'qituvchisi sinfni bo'y bo'yicha safga tizadi. U bir vaqtda faqat ikki o'quvchiga qaraydi: "Ali, Jasur — qaysi biringiz balandroq?" Javobga qarab ularning o'rnini almashtiradi yoki joyida qoldiradi. Kimni kim bilan solishtirishni o'qituvchi o'zi hal qiladi. Unga faqat qoida kerak: "balandi oldinda". sort — o'sha o'qituvchi, qoida esa — siz beradigan taqqoslash funksiyasi.
Reja: avval sort qoidasiz nima qilishini va nega shunday ekanini ko'ramiz. Keyin taqqoslash funksiyasi, uning ichidagi sikl va obyektlarni saralash. So'ng o'zbek harflari — o', g', sh, ch — va brauzerdagi kutilmagan farq. Oxirida sort ning eng xavfli xususiyati — asl massivni o'zgartirishi — va vazifalar dagi yangi imkoniyat.
2. Standart sort: hamma narsa satr
2.1 Satrlarda ishlaydi
Kichik harfli so'zlarda sort kutilgandek ishlaydi:
const taomlar = ["manti", "osh", "lag'mon"];
taomlar.sort();
console.log(taomlar); // [ "lag'mon", 'manti', 'osh' ]l, m, o — alifbo tartibida. Shuning uchun ko'pchilik sort ni "alifbo bo'yicha saralaydi" deb o'ylaydi. Aslida u boshqa ish qiladi — sonlarda bu darhol ko'rinadi.
2.2 Sonlarda — tuzoq
const sonlar = [10, 9, 1];
console.log(sonlar.sort()); // [ 1, 10, 9 ]10 — 9 dan oldin. Keyingi tugmasini bosib, sort ichida nima bo'lganini kuzating:
Lug'atdagi so'zlar kabi: "olma" "o'rik" dan oldin, chunki birinchi farq qilgan harf hal qiladi, so'zning uzunligi emas. sort sonlarni ham xuddi so'z kabi o'qidi: "10" ning birinchi belgisi "1", u "9" dan kichik — tamom.
2.3 Nega shunday qilingan?
Qoida standartda shunday yozilgan: taqqoslash funksiyasi berilmasa, sort elementlarni satrga aylantiradi va belgi kodlari bo'yicha solishtiradi. Sabab — massivda har xil turdagi qiymat bo'lishi mumkin: son, satr, null, obyekt. Ularning hammasini satrga aylantirish mumkin, demak satr tartibi — hamma uchun ishlaydigan yagona "umumiy" tartib. To'g'ri, lekin sonlar uchun foydasiz.
Bu qoidadan yana ikki g'alati natija chiqadi:
const mevalar = ["olma", "Behi", "anor", undefined, "zira"];
console.log(mevalar.sort());
// [ 'Behi', 'anor', 'olma', 'zira', undefined ]- Katta harf oldinda.
Bning kodi (66) har qanday kichik harfnikidan (97–122) kichik. Shuning uchun "Behi" "anor" dan oldin turdi. undefineddoim oxirida.sortuni umuman solishtirmaydi — to'g'ridan-to'g'ri oxiriga qo'yadi.
Tekshirib ko'ring:
[2, 100, 30].sort()nima qaytaradi?
Javob
[ 100, 2, 30 ]. Satr sifatida: "100", "2", "30". Birinchi belgilar — 1, 2, 3. Qolgan belgilar ahamiyatga ega emas: "100" birinchi belgisi tufayli eng oldinda.
3. Taqqoslash funksiyasi
3.1 (a, b) => a - b
Sonlarni son sifatida saralash uchun sort ga qoida beramiz:
const narxlar = [35000, 28000, 5000, 30000];
narxlar.sort((a, b) => a - b);
console.log(narxlar); // [ 5000, 28000, 30000, 35000 ]Endi choy — eng arzon, osh — eng qimmat. Jasur akaning taxtasi tayyor.
Taqqoslash funksiyasi (comparator) — ikki elementni olib, ulardan qaysi biri oldin turishini son bilan aytadigan callback. Inglizcha "compare" — "solishtirmoq". Uning imzosi boshqa HOF metodlarnikidan farq qiladi: (element, index, array) emas, (a, b) — ikki element. Callback imzosi darsida shu istisnoni aytib o'tgan edik.
3.2 Qaytgan son nimani bildiradi
sort callback qaytargan sonning faqat ishorasiga qaraydi:
| Callback qaytardi | Ma'nosi |
|---|---|
manfiy son (-1, -23000) |
a oldin turadi |
musbat son (1, 30000) |
b oldin turadi |
0 |
teng — o'zaro tartibi o'zgarmaydi |
Sxemada xuddi shu qoida — o'qituvchining savoli va uchta javob:
flowchart TD
S{"taqqosla(a, b) nima qaytardi?"}
S -- "manfiy" --> A["a oldin, b keyin"]
S -- "musbat" --> B["b oldin, a keyin"]
S -- "0" --> C["teng: o'z joyida qoladi"]a - b nega aynan shu qoidaga mos keladi? a kichik bo'lsa, ayirma manfiy — a oldin. a katta bo'lsa — musbat, b oldin. Teng bo'lsa — 0. Natija: kichigi oldinda, ya'ni o'sish tartibi.
Kamayish tartibi uchun ayirmani teskari oling:
const ballar = [78, 100, 9, 85];
ballar.sort((a, b) => b - a);
console.log(ballar); // [ 100, 85, 78, 9 ]O'zingiz to'ldiring. Callback (4, 7) bilan chaqirildi. a - b qaytaradi [:-3], demak oldin turadi [:4]. b - a bilan esa oldin turadi .
3.3 sort ichidan
Oldingi darslarda metodning "ichini" o'zimiz yozib chiqqan edik. Saralashning eng sodda usullaridan biri — qo'shib-joylash (insertion). Karta o'ynayotgan odam qo'lidagi kartalarni shunday tartiblaydi: har yangi kartani chapdagi tartiblangan kartalar orasidan o'z joyiga suqib qo'yadi.
function saralash(massiv, taqqosla) {
for (let i = 1; i < massiv.length; i++) {
const joriy = massiv[i];
let j = i - 1;
while (j >= 0 && taqqosla(massiv[j], joriy) > 0) {
massiv[j + 1] = massiv[j]; // kattasini o'ngga sur
j--;
}
massiv[j + 1] = joriy; // bo'shagan joyga qo'y
}
return massiv;
}
const narxlar = [35000, 28000, 5000, 30000];
console.log(saralash(narxlar, (a, b) => a - b));
// [ 5000, 28000, 30000, 35000 ]Uchta narsaga qarang:
- Callback faqat savolga javob beradi.
taqqosla(massiv[j], joriy) > 0— "chapdagisi keyin turishi kerakmi?". Kimni kim bilan solishtirish va elementlarni qayerga surishni sikl hal qiladi. - Massiv joyida o'zgaradi. Yangi massiv yaratilmadi —
massiv[j + 1] = ...aslining ichiga yozadi. Haqiqiysortham shunday; bu xususiyatning narxini «sortasl massivni o'zgartiradi» bo'limida ko'ramiz. - Qaytgani — o'sha massiv.
return massivyangi nusxa emas.
Haqiqiy sort ichida murakkabroq algoritm ishlaydi. Chrome va Node'dagi V8 dvigateli TimSort ni ishlatadi: u qisqa bo'laklarni xuddi shunday qo'shib-joylab saralaydi, keyin bo'laklarni birlashtiradi. Saralash algoritmlarini Oddiy saralashlar va JS sort ichidan darslarida batafsil o'rganamiz — hozir bilish shart emas.
3.4 Kim kim bilan solishtiriladi?
Callback ichiga console.log qo'yib, sort uni qanday chaqirishini ko'raylik:
const narxlar = [30000, 5000, 28000];
narxlar.sort((a, b) => {
console.log(`a=${a} b=${b}`);
return a - b;
});Konsolda:
a=5000 b=30000
a=28000 b=5000
a=28000 b=30000
a=28000 b=5000Ikki narsa ko'rinadi. Birinchisi: a har doim massivdagi birinchi element emas — Node bu yerda keyingi elementni a qilib berdi. Ikkinchisi: bir juftlik ikki marta solishtirildi. Bu tartib dvigatelga (Node va Chrome'da — V8) bog'liq, JavaScript standarti uni belgilamaydi. Shuning uchun callback'dan faqat bitta narsa talab qilinadi: istalgan ikki element uchun izchil javob bersin. (5000, 30000) ga "5000 oldin" degan bo'lsa, (30000, 5000) ga ham "5000 oldin" desin.
Tekshirib ko'ring:
[4, 2, 9].sort((a, b) => b - a)nima qaytaradi? Callback(2, 9)bilan chaqirilsa, nima javob beradi?
Javob
[ 9, 4, 2 ] — kamayish tartibi. (2, 9) uchun 9 - 2 = 7 — musbat, demak b (ya'ni 9) oldin turadi. Kattasi oldinda — kamayish.
4. Obyektlarni saralash
4.1 Bitta kalit bo'yicha
Real ma'lumot ko'pincha obyektlar massivi. Taqqoslash funksiyasi butun obyektlarni oladi — qaysi maydonni solishtirishni o'zimiz tanlaymiz:
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Ko'k choy", narx: 5000 },
{ nom: "Lag'mon", narx: 28000 },
];
menyu.sort((a, b) => a.narx - b.narx);
const nomlar = menyu.map((t) => t.nom);
console.log(nomlar); // [ "Ko'k choy", "Lag'mon", 'Osh' ]a va b — taomlar, ayiriladigani esa ularning narx lari. Natijani tekshirish uchun faqat nomlarni map bilan oldik.
4.2 Bir necha kalit bo'yicha
Lag'mon va manti narxi bir xil bo'lsa-chi? Jasur aka aytadi: "narx teng bo'lsa — nomi bo'yicha". Bu ikki pog'onali qoida:
const menyu = [
{ nom: "Manti", narx: 30000 },
{ nom: "Osh", narx: 35000 },
{ nom: "Lag'mon", narx: 30000 },
];
menyu.sort((a, b) => a.narx - b.narx || a.nom.localeCompare(b.nom));
console.log(menyu.map((t) => t.nom)); // [ "Lag'mon", 'Manti', 'Osh' ]Butun sir || operatorida (Mantiqiy operatorlar):
- Narxlar har xil bo'lsa,
a.narx - b.narx— nolmas son, ya'ni truthy.||uni qaytaradi, o'ng tomoni hisoblanmaydi ham. - Narxlar teng bo'lsa, ayirma
0— falsy. Shunda||o'ng tomonga o'tadi va nomlarni solishtiradi.
localeCompare — matnlarni solishtiradigan metod, uni «Matnni to'g'ri saralash» bo'limida batafsil ko'ramiz. Hozircha bilib qo'ying: u ham manfiy, musbat yoki 0 qaytaradi — xuddi taqqoslash funksiyasidek. Uchinchi kalit kerak bo'lsa, yana bir || qo'shiladi.
4.3 Barqaror saralash
Otabekning buyurtmalar ro'yxati kelish vaqti bo'yicha tartiblangan. Oshxona ekranida esa avval tayyorlanayotganlar, keyin tayyorlari turishi kerak:
const buyurtmalar = [
{ stol: 3, tayyor: true },
{ stol: 7, tayyor: false },
{ stol: 1, tayyor: true },
{ stol: 5, tayyor: false },
];
buyurtmalar.sort((a, b) => Number(a.tayyor) - Number(b.tayyor));
console.log(buyurtmalar.map((b) => b.stol)); // [ 7, 5, 3, 1 ]Number(false) — 0, Number(true) — 1 (Turlarni aniq o'zgartirish). Ayirma bo'yicha false lilar oldinga chiqadi.
Endi natijaga diqqat bilan qarang. Tayyorlanayotganlar orasida 7-stol 5-stoldan oldin — xuddi asl ro'yxatdagidek. Tayyorlar orasida ham 3-stol 1-stoldan oldin. Taqqoslash funksiyasi ular uchun 0 qaytardi va sort ularning o'zaro tartibini saqladi.
Barqaror saralash (stable sort) — teng elementlarning asl tartibi saqlanadigan saralash. Bu 2019-yildan (ES2019) standartda kafolatlangan. Undan oldin ba'zi brauzerlar teng elementlarni aralashtirib yuborishi mumkin edi — Chrome barqaror saralashga 2018-yilda, 70-versiyada o'tgan. Bugun barcha zamonaviy brauzer va Node'da shunday.
Barqarorlik amalda ikki kalitli saralashni ham osonlashtiradi: ro'yxat allaqachon vaqt bo'yicha tartiblangan bo'lsa, faqat holat bo'yicha saralash kifoya — vaqt tartibi guruhlar ichida o'zi saqlanadi.
Tekshirib ko'ring: Talabalar ro'yxati ism bo'yicha tartiblangan. Uni ball bo'yicha
(a, b) => b.ball - a.ballbilan saralasak, balli bir xil ikki talaba qaysi tartibda turadi?
Javob
Ism tartibida — xuddi saralashdan oldingidek. Ballari teng — callback 0 qaytaradi. Barqaror saralash teng elementlarning asl tartibini o'zgartirmaydi, asl tartib esa ism bo'yicha edi.
5. Matnni to'g'ri saralash: localeCompare
5.1 Katta-kichik harf
Standart sort "Behi" ni "anor" dan oldin qo'ydi — katta harf kodi kichik. Odam uchun esa bu xato: lug'atda "anor" birinchi. Matnni til qoidalari bo'yicha solishtirish uchun satrlarning localeCompare metodi bor:
console.log("anor".localeCompare("behi")); // -1
console.log("behi".localeCompare("anor")); // 1
console.log("osh".localeCompare("osh")); // 0Javoblari — taqqoslash funksiyasiga kerakli uchta qiymat. Demak uni to'g'ridan-to'g'ri callback ichida ishlatsa bo'ladi:
const mevalar = ["olma", "Behi", "anor"];
mevalar.sort((a, b) => a.localeCompare(b));
console.log(mevalar); // [ 'anor', 'Behi', 'olma' ]"Behi" endi o'z joyida — "anor" va "olma" orasida. localeCompare katta va kichik b ni bitta harf deb biladi.
5.2 O'zbek harflari
O'zbek lotin alifbosi z bilan tugamaydi: undan keyin o', g', sh, ch keladi. Standart sort va tilsiz localeCompare buni bilmaydi:
const sozlar = ["zira", "o'rik", "olma", "choy", "g'oza", "gilos"];
console.log(sozlar.sort((a, b) => a.localeCompare(b)).join(", "));
// choy, g'oza, gilos, o'rik, olma, zira"choy" — boshida, "o'rik" — "olma" dan oldin. Bu ingliz tilidagi tartib: apostrof harflardan oldin turadi, ch esa oddiy c va h.
localeCompare ning ikkinchi argumenti — til kodi. O'zbek tili uchun — "uz":
const sozlar = ["zira", "o'rik", "olma", "choy", "g'oza", "gilos"];
const tartib = sozlar.sort((a, b) => a.localeCompare(b, "uz"));
console.log(tartib.join(", "));
// gilos, olma, zira, o'rik, g'oza, choyEndi tartib o'zbek alifbosidagidek: z dan keyin o', keyin g', oxirida ch. Bu natija Node 24 da olingan — unda xalqaro tillar ma'lumoti to'liq. Node 24 apostrofning uch xil yozilishini (', ‘, ʻ) ham bir xil tushunadi. Faqat ng alohida harf deb hisoblanmaydi — u n va g sifatida saralanadi.
5.3 Brauzerda boshqacha!
Xuddi shu kodni Chrome konsolida ishga tushiring. Biz Chrome 154 da sinadik:
const sozlar = ["zira", "o'rik", "olma", "choy", "g'oza", "gilos"];
sozlar.sort((a, b) => a.localeCompare(b, "uz"));
console.log(sozlar.join(", "));Konsolda:
choy, g'oza, gilos, o'rik, olma, zira"uz" yozilgan bo'lsa ham — inglizcha tartib. Sabab: brauzerlar hajmni tejash uchun hamma tillarning saralash qoidalarini o'zi bilan olib yurmaydi. Chrome'da o'zbek tili qoidalari yo'q, u jimgina o'zining standart tiliga qaytadi.
Buni tekshirish mumkin. JavaScript'da Intl degan tayyor obyekt bor — tilga bog'liq ishlar (sana, son, matn tartibi) uchun vositalar to'plami. Uning Intl.Collator qismi matnlarni solishtiradi:
console.log(Intl.Collator.supportedLocalesOf(["uz", "ru", "tr"]));
// Chrome 154: [ 'ru', 'tr' ] Node 24: [ 'uz', 'ru', 'tr' ]supportedLocalesOf — "shu tillardan qaysilarini qo'llaysan?" degan savol. Chrome rus va turk tillarini qo'llaydi, o'zbekchani — yo'q. Node esa uchalasini ham.
Bundan amaliy xulosa: o'zbekcha alifbo tartibi muhim bo'lsa (masalan, mijozlar ro'yxati), saralashni serverda — Node'da — qiling yoki o'zingiz alifbo jadvali bilan taqqoslash funksiyasini yozing. Ikkinchisini 3-mashqda qilamiz.
5.4 Intl.Collator — tayyor taqqoslash funksiyasi
localeCompare har chaqiruvda til qoidalarini qaytadan tayyorlaydi. Ming so'zni saralaganda bu ish minglab marta takrorlanadi. Buning o'rniga qoidalarni bir marta tayyorlab qo'yish mumkin:
const uzTartib = new Intl.Collator("uz", { numeric: true });
const stollar = ["10-stol", "9-stol", "1-stol"];
console.log(stollar.sort(uzTartib.compare));
// [ '1-stol', '9-stol', '10-stol' ]new Intl.Collator("uz", ...) — o'zbek tili qoidalari bo'yicha solishtiruvchi yasaydi. new so'zini Konstruktor funksiya darsida o'rganamiz — hozir "yangisini yasa" deb o'qing. Uning compare xususiyati — tayyor taqqoslash funksiyasi, uni qavssiz beramiz.
{ numeric: true } — matn ichidagi sonlarni son sifatida solishtir. Usiz "10-stol" "9-stol" dan oldin turardi — o'sha "10" < "9" tuzog'i. Intl.Collator ning boshqa sozlamalarini Intl.Collator va Intl.Segmenter darsida ko'ramiz.
Tekshirib ko'ring: Telegram bot foydalanuvchilar ismini o'zbek alifbosi bo'yicha saralab yuborishi kerak. Bot serverda, Node 24 da ishlaydi. Qaysi taqqoslash funksiyasi to'g'ri:
(a, b) => a.localeCompare(b)yoki(a, b) => a.localeCompare(b, "uz")?
Javob
Ikkinchisi. Til kodisiz localeCompare muhitning standart tilini oladi — ko'pincha ingliz. Shunda "O'tkir" "Olim" dan oldin, "Shuhrat" esa "Sardor" dan oldin chiqadi. Node 24 da "uz" qoidalari bor, shuning uchun serverda to'g'ri ishlaydi. Shu kod brauzerda ishlasa — Chrome'da yana inglizcha tartib bo'lardi.
6. sort asl massivni o'zgartiradi
«sort ichidan» bo'limida ko'rdik: saralash massivning o'zida bo'ladi. Element qo'shish va olib tashlash darsidagi atama bilan — sort mutatsiya qiladi. Bundan tashqari, u yangi massiv emas, o'sha massivni qaytaradi:
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Ko'k choy", narx: 5000 },
];
const arzondan = menyu.sort((a, b) => a.narx - b.narx);
console.log(menyu[0].nom); // Ko'k choy
console.log(arzondan === menyu); // trueOtabek faqat "arzondan qimmatga" ko'rinishini olmoqchi edi. Lekin asl menyu ham qayta tartiblandi: arzondan va menyu — bitta massiv (Havola semantikasi). Menyuning boshqa joyda ishlatiladigan tartibi (masalan, oshpaz kelishilgan tartib) yo'qoldi.
To'g'ri yo'l — avval nusxa, keyin saralash:
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Ko'k choy", narx: 5000 },
];
const arzondan = [...menyu].sort((a, b) => a.narx - b.narx);
console.log(menyu[0].nom); // Osh
console.log(arzondan[0].nom); // Ko'k choy[...menyu] — yangi massiv (Spread), sort o'shani tartibladi. filter, map va slice ham yangi massiv qaytaradi — ularning natijasini saralash xavfsiz: menyu.filter(...).sort(...).
Diqqat:
sort— HOF metodlar orasida kam uchraydigan mutatsiya qiluvchi metod.map,filter,reduceasl massivga tegmaydi;sortesa tegadi. Bu farqni unutish — real loyihalardagi eng ko'p uchraydigan xatolardan. 2023-yilda JavaScript'ga buning uchun alohida metod qo'shildi:toSorted— asl massivga tegmay, saralangan nusxa qaytaradi. Uni keyingi darsda, Nusxa bilan o'zgartirish da o'rganamiz.
Tekshirib ko'ring:
const ballar = [5, 3, 9]; const eng = ballar.sort((a, b) => b - a)[0];dan keyinballar[0]nechaga teng?
Javob
9. Sizga faqat eng katta son kerak edi, lekin sort ballar ning o'zini kamayish tartibiga keltirdi. Eng kattasini topish uchun saralash shart ham emas: Math.max(...ballar) (Math obyekti).
7. Ko'p uchraydigan xatolar
7.1 Sonlarni taqqoslash funksiyasisiz saralash
«Nega bu kerak?» bo'limidagi menyu: [35000, 28000, 5000, 30000].sort() — [ 28000, 30000, 35000, 5000 ]. Xato xabari yo'q. Kichik sinovda ([3, 1, 2]) hammasi to'g'ri chiqadi — xato faqat xonalar soni har xil bo'lganda ko'rinadi. Tuzatish: sonlar uchun doim (a, b) => a - b.
7.2 Taqqoslash funksiyasi true/false qaytaradi
Eski maqolalarda ba'zan shunday yozilgan:
const sonlar = [5, 1, 4, 2, 3];
sonlar.sort((a, b) => a > b);
console.log(sonlar); // [ 5, 1, 4, 2, 3 ]Hech narsa o'zgarmadi! a > b — true yoki false, son sifatida 1 yoki 0. Manfiy javob hech qachon chiqmaydi — sort hech qachon "a oldin" degan javobni eshitmaydi. Ba'zi eski dvigatellarda bu tasodifan ishlagan, shuning uchun hali ham internetda uchraydi. Tuzatish: (a, b) => a - b.
7.3 Satrlarni ayirish
const ismlar = ["Zafar", "Ali", "Malika"];
ismlar.sort((a, b) => a - b);
console.log(ismlar); // [ 'Zafar', 'Ali', 'Malika' ]Yana o'zgarmadi. "Zafar" - "Ali" — NaN (Yashirin coercion). sort NaN ni 0 deb qabul qiladi — "teng", tartibni o'zgartirma. Tuzatish: satrlar uchun a.localeCompare(b).
7.4 Saralangan nusxa o'rniga aslini o'zgartirish
«sort asl massivni o'zgartiradi» bo'limidagi menyu: const arzondan = menyu.sort(...) — menyu ning ham tartibi buzildi. Funksiya ichida bo'lsa, xato yanada yashirin: funksiya argument sifatida olgan massivni chaqiruvchi bilmagan holda o'zgartiradi. Tuzatish: [...menyu].sort(...) yoki keyingi darsdagi toSorted.
8. Mashqlar
1-mashq (oson): Imtihon natijalari
Ballarni eng yuqorisidan boshlab saralang. Avval taqqoslash funksiyasisiz sinab ko'ring va natija nega noto'g'ri ekanini tushuntiring.
const ballar = [78, 100, 9, 85];Yechim
const ballar = [78, 100, 9, 85];
console.log([...ballar].sort()); // [ 100, 78, 85, 9 ]
console.log([...ballar].sort((a, b) => b - a)); // [ 100, 85, 78, 9 ]Birinchisida 100 tasodifan oldinda: satr sifatida "1" boshqalardan kichik. Lekin 9 oxirida, 85 esa 78 dan keyin — bu kamayish ham, o'sish ham emas. Ikkinchisi — kamayish: b - a. Har gal [...ballar] nusxa oldik, shuning uchun asl ballar o'zgarmadi.
2-mashq (o'rta): Taksi haydovchilari
Taksi ilovasi haydovchilarni reyting bo'yicha ko'rsatadi: avval reytingi yuqorilari. Reytingi teng bo'lsa — ismi o'zbek alifbosi bo'yicha. Kod Node'da ishlaydi.
Ishora: ikki pog'onali qoida — «Bir necha kalit bo'yicha» bo'limidagi ||. Ismlar uchun — localeCompare(…, "uz").
const haydovchilar = [
{ ism: "Shuhrat", reyting: 4.9 },
{ ism: "Olim", reyting: 4.7 },
{ ism: "O'tkir", reyting: 4.9 },
{ ism: "Zafar", reyting: 4.9 },
{ ism: "Akmal", reyting: 4.7 },
];Yechim
const haydovchilar = [
{ ism: "Shuhrat", reyting: 4.9 },
{ ism: "Olim", reyting: 4.7 },
{ ism: "O'tkir", reyting: 4.9 },
{ ism: "Zafar", reyting: 4.9 },
{ ism: "Akmal", reyting: 4.7 },
];
haydovchilar.sort(
(a, b) => b.reyting - a.reyting || a.ism.localeCompare(b.ism, "uz"),
);
for (const h of haydovchilar) {
console.log(`${h.reyting} ${h.ism}`);
}Konsolda:
4.9 Zafar
4.9 O'tkir
4.9 Shuhrat
4.7 Akmal
4.7 Olim4.9 lik uchtasi o'zbek alifbosi tartibida: z, o', sh. Tilsiz localeCompare bilan "O'tkir" birinchi chiqardi. Reytinglar kasr son, lekin b.reyting - a.reyting ishorasi to'g'ri — kasr xatosi tartibga ta'sir qilmaydi.
3-mashq (qiyin): Brauzer uchun o'zbekcha tartib
Chrome'da localeCompare(…, "uz") ishlamasligini ko'rdik. O'zingizning uzTaqqosla(a, b) funksiyangizni yozing. U kichik harfli so'zlarni o'zbek alifbosi bo'yicha solishtirsin:
alifbo— 28 ta harf massivi:a b d e f g h i j k l m n o p q r s t u v x y z o' g' sh ch.harflar(soz)— so'zni harflarga bo'ladi. Navbatdagi ikki belgi (slice(i, i + 2)) alifboda bo'lsa (o',g',sh,ch), u bitta harf. Aks holda — bitta belgi.uzTaqqosla— ikki so'zning harflarini birinchisidan boshlab solishtiradi. Birinchi farq qilgan juftlikda harflarning alifbodagi o'rinlari ayirmasini (indexOf) qaytaradi. Farq topilmasa — qisqa so'z oldin.
Natijani Node'dagi localeCompare(…, "uz") bilan solishtiring.
Yechim
const alifbo = [
"a", "b", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "x", "y", "z",
"o'", "g'", "sh", "ch",
];
function harflar(soz) {
const natija = [];
let i = 0;
while (i < soz.length) {
const juft = soz.slice(i, i + 2);
if (alifbo.includes(juft)) {
natija.push(juft);
i += 2;
} else {
natija.push(soz[i]);
i += 1;
}
}
return natija;
}
function uzTaqqosla(a, b) {
const x = harflar(a.toLowerCase());
const y = harflar(b.toLowerCase());
for (let i = 0; i < Math.min(x.length, y.length); i++) {
const farq = alifbo.indexOf(x[i]) - alifbo.indexOf(y[i]);
if (farq !== 0) {
return farq;
}
}
return x.length - y.length;
}
const sozlar = ["choy", "zira", "o'rik", "olma", "shaftoli", "g'oza"];
const bizniki = [...sozlar].sort(uzTaqqosla);
const node = [...sozlar].sort((a, b) => a.localeCompare(b, "uz"));
console.log(bizniki.join(", "));
console.log(node.join(", "));Konsolda:
olma, zira, o'rik, g'oza, shaftoli, choy
olma, zira, o'rik, g'oza, shaftoli, choyIkki qator bir xil. harflar("shaftoli") — sh, a, f, t, o, l, i: yetti harf, sakkiz belgi. Farq topilmasa, qisqa so'z oldin: "osh" "oshxona" dan oldin. Bu funksiya brauzerda ham, Node'da ham bir xil ishlaydi — chunki u til ma'lumotiga emas, o'z jadvaliga tayanadi.
Chegaralari ham bor: alifbodan tashqari belgilar (ʻ, raqam, bo'sh joy) indexOf da -1 beradi va hammasidan oldin turadi. Apostrofning boshqa yozilishlarini oldindan ' ga almashtirish kerak. Real loyihada bunday jadvalni sinab ko'rilgan kutubxonadan olishadi yoki saralashni serverga topshirishadi.
4-mashq: Vazifalar qadami — bajarilmaganlar tepada
vazifalar ga birinchi yangi imkoniyat qo'shamiz. Hozir vazifalar qo'shilgan tartibida turadi: bajarilgani ham ro'yxat o'rtasida qolib ketadi. Talab:
- Bajarilmagan vazifalar ro'yxat tepasida, bajarilganlar — pastda.
- Har guruh ichida tartib o'zgarmasin — qo'shilgan tartibi.
holat.vazifalarning o'zi saralanmasin — faqat ekranga chiqadigan ro'yxat.
Yangi branch: git switch -c feature/saralash. Bu safar feature/ — xulq o'zgaradi. reduce darsidan keyin korinadiganlar shunday:
function korinadiganlar() {
return holat.vazifalar.filter(
(vazifa) => mosmi(vazifa, holat.filtr),
);
}Ishora: «Barqaror saralash» bo'limidagi Number(a.tayyor) - Number(b.tayyor) ni eslang.
Yechim
"3. Hisoblovchi funksiyalar" bo'limiga, mosmi dan keyin — taqqoslash funksiyasi:
function faollarOldin(a, b) {
return Number(a.bajarildi) - Number(b.bajarildi);
}korinadiganlar — filtrdan keyin saralash:
function korinadiganlar() {
return holat.vazifalar
.filter((vazifa) => mosmi(vazifa, holat.filtr))
.sort(faollarOldin);
}Uchala talab qanday bajarildi:
- Faollar tepada. Bajarilmagan —
0, bajarilgan —1; ayirma bo'yicha0lar oldin. - Guruh ichida tartib saqlanadi. Bir guruhdagi ikki vazifa uchun javob
0— barqaror saralash ularni qo'shilgan tartibida qoldiradi.idbo'yicha ikkinchi kalit kerak emas. holatsaralanmaydi.sortfilteryasagan yangi massivni tartibladi. «Hammasi» filtrida hamfilteryangi massiv qaytaradi — barcha elementlar o'tgan bo'lsa ham.
Nega holat.vazifalar.sort(...) emas? Node'da ikkala variantni bir xil harakatlar bilan solishtiring: 1-vazifani belgilaymiz, keyin qaytaramiz.
const vazifalar = [
{ id: 1, bajarildi: false },
{ id: 2, bajarildi: true },
{ id: 3, bajarildi: false },
];
function faollarOldin(a, b) {
return Number(a.bajarildi) - Number(b.bajarildi);
}
const idlar = (royxat) => royxat.map((v) => v.id).join(",");
const tozasi = () => vazifalar.filter(() => true).sort(faollarOldin);
const buzadigani = () => vazifalar.sort(faollarOldin);
for (const korsat of [tozasi, buzadigani]) {
vazifalar.sort((a, b) => a.id - b.id); // boshlang'ich holat
vazifalar[0].bajarildi = false;
const qadamlar = [idlar(korsat())];
vazifalar.find((v) => v.id === 1).bajarildi = true;
qadamlar.push(idlar(korsat()));
vazifalar.find((v) => v.id === 1).bajarildi = false;
qadamlar.push(idlar(korsat()));
console.log(qadamlar.join(" → "), "| holat:", idlar(vazifalar));
}Konsolda:
1,3,2 → 3,1,2 → 1,3,2 | holat: 1,2,3
1,3,2 → 3,1,2 → 3,1,2 | holat: 3,1,2Birinchi qator — bizning yechim: 1-vazifa qaytarilganda ro'yxat boshiga, o'z joyiga qaytdi. holat tartibi — 1,2,3, o'zgarmagan. Ikkinchi qator — holat.vazifalar.sort(...): qaytarilgan 1-vazifa endi 3-dan keyin qoldi. Har render holat ning o'zini qayta tartibladi va asl tartib yo'qoldi. Xato xabari yo'q — faqat foydalanuvchi "nega vazifam joyini o'zgartirdi?" deb hayron qoladi. (filter(() => true) bu yerda faqat "yangi massiv yasash" uchun — haqiqiy kodda uning o'rnida mosmi bilan filtr turadi.)
Brauzerda tekshiring:
- Ochilganda: "Non olish", "Onamga qo'ng'iroq qilish", keyin chizilgan "DOM darsini takrorlash".
- "Non olish" ni belgilang — u pastga tushadi, fokus uning katagida qoladi. Qaytaring — u yana birinchi o'rinda.
- Yangi vazifa qo'shing — u faollarning oxirida, bajarilganlardan oldin paydo bo'ladi.
- «Faol» va «Bajarilgan» filtrlari, tahrirlash,
Esc, o'chirish — avvalgidek.
Belgilangan vazifa pastga tushganda fokus u bilan birga ketadi: fokusla uni id bo'yicha topadi, joyi bo'yicha emas. Klaviatura bilan ishlaydigan Bobur ham, NVDA ishlatadigan Malika ham fokusni yo'qotmaydi.
Commit va main ga qo'shish:
git add assets/js/vazifalar.js
git commit -m "Ro'yxat: bajarilmagan vazifalar tepada"
git switch main
git merge feature/saralash
git branch -d feature/saralash
git push9. Real ishda
- Jadval ustunlari. Internet do'kondagi "narx bo'yicha", "yangilari avval", "reyting bo'yicha" tugmalari — har biri bitta taqqoslash funksiyasi. Admin paneldagi jadval sarlavhasini bosib saralash ham shunday.
- Ismlar ro'yxati. Maktab jurnali, xodimlar ro'yxati, Telegram kontaktlari — alifbo tartibi. O'zbekcha tartib kerak bo'lsa, saralashni serverda
localeCompare(…, "uz")yokiIntl.Collatorbilan qiling — brauzerga ishonmang. - Ma'lumotlar bazasi. Katta ro'yxatlarni odatda baza saralab beradi (
ORDER BY— SQL qismida). Lekin bazadan kelgan kichik ro'yxatni foydalanuvchi bosgan tugmaga qarab qayta saralash — brauzerdagisortning ishi. - Intervyu. "
[10, 9, 1].sort()nima qaytaradi va nega?", "taqqoslash funksiyasi nima qaytarishi kerak?", "sortbarqarormi?" — junior intervyusida tez-tez beriladi. Javoblar:[1, 10, 9]— satr tartibi; manfiy, musbat yoki0; ha, ES2019 dan.
Xulosa
sorttaqqoslash funksiyasisiz elementlarni satrga aylantirib solishtiradi:[10, 9, 1]→[1, 10, 9].- Taqqoslash funksiyasi
(a, b)oladi va son qaytaradi: manfiy —aoldin, musbat —boldin,0— joyida. Sonlar:a - b(o'sish),b - a(kamayish). - Bir necha kalit —
||bilan:a.narx - b.narx || a.nom.localeCompare(b.nom). Saralash barqaror: teng elementlar tartibi saqlanadi. - Matnlar —
localeCompare(b, "uz")yokinew Intl.Collator("uz").compare. Node 24 o'zbek alifbosini biladi, Chrome — yo'q. sortasl massivni o'zgartiradi va o'shani qaytaradi. Asli kerak bo'lsa — avval nusxa:[...massiv].sort(...).
Keyingi dars: Nusxa bilan o'zgartirish: toSorted, toReversed, toSpliced, with — asl massivga tegmasdan saralash, teskari aylantirish va o'zgartirishning zamonaviy usullari.
Manbalar
- MDN: "Array.prototype.sort()", "String.prototype.localeCompare()", "Intl.Collator" — developer.mozilla.org
- ECMAScript 2025 Language Specification: "Array.prototype.sort", "SortCompare" — tc39.es/ecma262
- V8 blog: "Getting things sorted in V8" (2018) — v8.dev/blog/array-sort
- web-features: "Stable array sort" — Baseline, Chrome 70 dan
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!