Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. Zanjir qanday ishlaydi
- 2.1 Har metod — yangi massiv
- 2.2 Pipeline
- 2.3 Nomli bosqichlar
- 2.4 Formatlash
- 3. Zanjir qayerda uziladi
- 3.1 Massiv qaytarmaydigan metodlar
- 3.2 sort zanjirda
- 4. Zanjirni tekshirish
- 5. Zanjirning narxi
- 5.1 Har bosqich — to'liq o'tish va yangi massiv
- 5.2 O'lchov: million buyurtma
- 5.3 Bosqichlar tartibi
- 6. Erta chiqish
- 6.1 Zanjir to'xtamaydi
- 6.2 Erta chiqadigan metodlar
- 7. Qachon zanjir, qachon sikl
- 8. Ko'p uchraydigan xatolar
- 8.1 forEach zanjir o'rtasida
- 8.2 Zanjir boshida sort
- 8.3 map dan keyin kerakli maydon yo'qoladi
- 8.4 Zanjir o'rtasidagi reduce boshlang'ich qiymatsiz
- 8.5 Juda uzun zanjir
- 9. Mashqlar
- 1-mashq (oson): O'tganlar ro'yxati
- 2-mashq (o'rta): Taksi: qimmat safarlarning o'rtachasi
- 3-mashq (qiyin): Kunlik hisobot — eng ko'p tushum bergan ikki taom
- 4-mashq: Vazifalar qadami — oqimni o'lchash va hujjatlashtirish
- 10. Real ishda
- Xulosa
- Manbalar
JavaScript metod zanjiri: filter, map, reduce bilan ma'lumot pipeline
Qisqacha: Massiv qaytaradigan metodlarni nuqta bilan ketma-ket ulash mumkin:
buyurtmalar.filter(tolanganmi).map(summasi).reduce(qosh, 0). Har bosqich oldingisining natijasini oladi — bu pipeline. Zanjir o'qishga oson, lekin har bosqich butun massivni aylanadi va yangi massiv yasaydi. Odatdagi ro'yxatlarda farq sezilmaydi; million elementda yoki "birinchi topilgani yetarli" holatda oddiy sikl tezroq.
Bu darsda
filter,map,toSorted,reduceni bitta o'qiluvchan zanjirga ulay olasiz va uni to'g'ri formatlaysiz.- Zanjir qaysi metodlarda uzilishini bilasiz.
- Zanjirni bosqichma-bosqich tekshirib, xatoni topa olasiz.
- Oraliq massivlar narxini va erta chiqish foydasini o'lchab ko'rsata olasiz.
vazifalardagi ma'lumot oqimini o'lchab, hujjatlashtirasiz va modulni yakunlaysiz.
Oldin bilishingiz kerak: filter, reduce, Nusxa bilan o'zgartirish, Guruhlash: Object.groupBy, Pure funksiya va side effect, Ko'p elementni samarali chizish.
1. Nega bu kerak?
Kun oxirida Jasur aka so'raydi: "bugun to'langan buyurtmalardan qancha pul tushdi?" Ma'lumot — buyurtmalar ro'yxati. 08-qism uslubida yozamiz:
const buyurtmalar = [
{ stol: 3, summa: 120000, tolandi: true },
{ stol: 1, summa: 45000, tolandi: false },
{ stol: 7, summa: 30000, tolandi: true },
];
let tushum = 0;
for (const b of buyurtmalar) {
if (b.tolandi) {
tushum += b.summa;
}
}
console.log(tushum); // 150000Ishlaydi. Endi so'nggi to'qqiz darsda o'rganganimiz bilan:
const buyurtmalar = [
{ stol: 3, summa: 120000, tolandi: true },
{ stol: 1, summa: 45000, tolandi: false },
{ stol: 7, summa: 30000, tolandi: true },
];
const tushum = buyurtmalar
.filter((b) => b.tolandi)
.map((b) => b.summa)
.reduce((jami, s) => jami + s, 0);
console.log(tushum); // 150000Uch qator — uch fe'l: tanla, ol, qo'sh. Ularni yuqoridan pastga o'qisangiz, savolning o'zi chiqadi. Bu — metod zanjiri va bugungi darsning mavzusi.
Hayotdan o'xshatish: konveyer. Non zavodida xamir birinchi stansiyada bo'linadi, ikkinchisida shakl oladi, uchinchisida pishadi. Har stansiya faqat oldingisidan kelganini oladi va o'zining bitta ishini qiladi. Bir stansiyani olib tashlash yoki yangisini qo'shish oson. Metod zanjiri ham shunday: har metod — bitta stansiya.
filter darsida birinchi zanjirni ko'rgan edik va "o'qiluvchanlik, tezlik va qachon oddiy sikl yaxshiroq — keyinroq" degan edik. Callback imzosi darsida ham "katta ma'lumotda metodlar zanjirini o'lchaymiz" deb va'da bergan edik. Bugun ikkalasini bajaramiz: avval zanjirni yozish va o'qish qoidalari, keyin uning narxi — haqiqiy o'lchovlar bilan.
2. Zanjir qanday ishlaydi
2.1 Har metod — yangi massiv
Zanjirning siri oddiy: filter massiv qaytaradi, massivda esa map bor. map ham massiv qaytaradi — unda reduce bor. Nuqta oldingi metodning natijasiga murojaat qiladi.
Bosqichlarni alohida o'zgaruvchilarga ajratsak, bu yaqqol ko'rinadi:
const buyurtmalar = [
{ stol: 3, summa: 120000, tolandi: true },
{ stol: 1, summa: 45000, tolandi: false },
{ stol: 7, summa: 30000, tolandi: true },
];
const tolanganlar = buyurtmalar.filter((b) => b.tolandi);
const summalar = tolanganlar.map((b) => b.summa);
const tushum = summalar.reduce((jami, s) => jami + s, 0);
console.log(tolanganlar.length, summalar, tushum);
// 2 [ 120000, 30000 ] 150000Zanjir aynan shu uch qator — faqat oraliq nomlarsiz. Sxemada har bosqichdan keyin nima qolishiga qarang:
flowchart LR
A["buyurtmalar: 3 ta obyekt"] -- "filter: to'landimi?" --> B["2 ta obyekt"]
B -- "map: summasini ol" --> C["2 ta son"]
C -- "reduce: qo'sh" --> D["150000"]Massiv har bosqichda "torayadi" yoki "shaklini o'zgartiradi": obyektlar → kamroq obyektlar → sonlar → bitta son.
2.2 Pipeline
Ma'lumot pipeline (data pipeline) — ma'lumot ketma-ket bosqichlardan o'tadigan, har bosqich oldingisining natijasini oladigan tuzilma. Inglizcha "pipeline" — "quvur": suv bir uchidan kiradi, yo'lda filtrlardan o'tadi, boshqa uchidan tozalanib chiqadi. Bu so'zni dasturchilar juda ko'p ishlatadi: ma'lumot pipeline, CI pipeline (34-qismda), build pipeline.
Yaxshi pipeline'ning uchta belgisi:
- Har bosqich — bitta ish.
filterfaqat tanlaydi,mapfaqat aylantiradi. - Bosqichlar toza. Callback'lar tashqi narsani o'zgartirmaydi (Pure funksiya). Shuning uchun bosqichlarni ko'chirish, olib tashlash va alohida sinash xavfsiz.
- Kirish o'zgarmaydi.
buyurtmalarzanjirdan keyin ham o'sha-o'sha. Har bosqich yangi massiv beradi.
2.3 Nomli bosqichlar
Callback'larga nom bersangiz, zanjir gap kabi o'qiladi:
const buyurtmalar = [
{ stol: 3, summa: 120000, tolandi: true },
{ stol: 1, summa: 45000, tolandi: false },
{ stol: 7, summa: 30000, tolandi: true },
];
const tolanganmi = (b) => b.tolandi;
const summasi = (b) => b.summa;
const qosh = (jami, son) => jami + son;
const tushum = buyurtmalar
.filter(tolanganmi)
.map(summasi)
.reduce(qosh, 0);
console.log(tushum); // 150000"Buyurtmalardan to'langanmi — tanla, summasini — ol, qo'sh". Nomlar kurs qoidasiga mos: predikat — "-mi" bilan (tolanganmi), qiymat qaytaruvchi — natija nomi (summasi). Bonus: qosh va summasi ni boshqa zanjirlarda ham ishlatish mumkin.
Qachon nom berish kerak? Callback bir qarashda tushunarli bo'lsa ((b) => b.summa) — joyida qoldiring. Shart murakkab bo'lsa yoki bir necha joyda takrorlansa — nomli funksiyaga chiqaring.
2.4 Formatlash
«Nomli bosqichlar» dagi zanjir kelishilgan usulda yozilgan — har metod alohida qatorda, nuqta bilan boshlanadi:
const tushum = buyurtmalar
.filter(tolanganmi)
.map(summasi)
.reduce(qosh, 0);Sabablari: bosqichlar ustun bo'lib turadi va ularni sanash oson; bitta bosqichni izohga olish yoki o'chirish — bitta qator; telefonda gorizontal aylantirish yo'q. Prettier ham shunday qiladi: 06-qismda CSS uchun ishlatgan bu vosita JavaScript zanjirini ham shunday formatlaydi (ESLint va Prettier). Ikki-uch qisqa metodli zanjir 70 belgiga sig'sa, uni bitta qatorda qoldirish ham mumkin: [4, 7].map(ikkilan).join(", ").
Tekshirib ko'ring:
[4, 7, 10, 3].filter((x) => x > 3).map((x) => x * 2).reduce((a, x) => a + x, 0)nima qaytaradi? Har bosqichdan keyin massiv qanday?
Javob
42. filter dan keyin — [4, 7, 10] (3 o'tmadi). map dan keyin — [8, 14, 20]. reduce — 8 + 14 + 20 = 42. Har bosqich oldingisining natijasini oldi.
3. Zanjir qayerda uziladi
3.1 Massiv qaytarmaydigan metodlar
Zanjir faqat metod massiv qaytarguncha davom etadi. Massiv qaytarmaydigan metod — zanjirning oxiri:
| Metod | Qaytaradi | Keyin zanjir? |
|---|---|---|
filter, map, flatMap, slice, toSorted |
yangi massiv | davom etadi |
reduce |
istalgan qiymat | faqat natija massiv bo'lsa |
find, at |
bitta element | yo'q |
some, every, includes |
true/false |
yo'q |
join |
satr | satr metodlari |
forEach |
undefined |
yo'q |
Eng ko'p uchraydigan xato — forEach ni zanjir o'rtasiga qo'yish:
const narxlar = [35000, 28000, 5000];
narxlar
.forEach((n) => console.log(n))
.map((n) => n * 2);TypeError: Cannot read properties of undefined (reading 'map')Tarjimasi: "undefined ning xususiyatlarini o'qib bo'lmaydi (map ni o'qishda)". forEach undefined qaytardi (Callback imzosi dagi jadval), keyingi nuqta esa undefined.map ni qidirdi. Xabarda forEach haqida bir so'z ham yo'q — u faqat keyingi bosqich nomini aytadi. Qoida: "Cannot read properties of undefined (reading 'X')" ko'rsangiz — X dan oldingi bosqichni tekshiring. Tuzatish: forEach faqat zanjir oxirida bo'lishi mumkin.
Mutatsiya qiluvchi metodlar ham tuzoq qo'yadi. push massiv emas, yangi uzunlikni qaytaradi — keyingi .filter son ustida chaqiriladi va ... .filter is not a function xatosi chiqadi.
3.2 sort zanjirda
sort massiv qaytaradi, shuning uchun zanjir uzilmaydi. Lekin u o'sha massivni qaytaradi va uni o'zgartiradi (sort):
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Choy", narx: 5000 },
];
const nomlar = menyu
.sort((a, b) => a.narx - b.narx)
.map((t) => t.nom);
console.log(nomlar); // [ 'Choy', 'Osh' ]
console.log(menyu[0].nom); // ChoyFaqat nomlar ro'yxatini olmoqchi edik, lekin menyu ning tartibi ham buzildi. Zanjir boshidagi sort — kirish ma'lumotini o'zgartiradi va pipeline'ning uchinchi belgisini buzadi. Tuzatish: toSorted (Nusxa bilan o'zgartirish). Zanjir o'rtasidagi sort (filter dan keyin) xavfsiz — u oraliq massivni o'zgartiradi. Lekin toSorted har joyda xavfsiz va o'qigan odamni o'ylatmaydi.
Tekshirib ko'ring: Quyidagi zanjirda xato bormi?
buyurtmalar.filter((b) => b.tolandi).find((b) => b.summa > 100000).map((b) => b.stol)
Javob
Bor. find massiv emas, bitta obyekt (yoki undefined) qaytaradi — obyektda map yo'q. Topilsa — ... .map is not a function, topilmasa — Cannot read properties of undefined (reading 'map'). Bitta stol kerak bo'lsa — .find(...)?.stol. Hammasi kerak bo'lsa — find o'rniga filter.
4. Zanjirni tekshirish
Zanjir noto'g'ri natija bersa, qaysi bosqichda buzilganini qanday topasiz? Uchta usul bor.
1. Bosqichlarni o'zgaruvchilarga ajrating. «Har metod — yangi massiv» bo'limidagidek. Har o'zgaruvchini chiqarib ko'ring. Zanjir ichidagi xato darhol bitta qatorga tushadi.
2. console.table bilan ko'ring. Obyektlar massivini jadval qilib chiqaradi (console API):
const tolanganlar = buyurtmalar.filter(tolanganmi);
console.table(tolanganlar);Jadvalda tolandi ustuniga qarab, filtr to'g'ri ishlaganini bir qarashda ko'rasiz.
3. Callback ichida to'xtash nuqtasi. DevTools'da callback qatoriga breakpoint qo'ying (DevTools bilan debug qilish). Har element uchun to'xtaydi va uning qiymatini ko'rsatadi. Nomli callback'larga (tolanganmi) to'xtash nuqtasini qo'yish ayniqsa oson.
Muammo topilgach, o'zgaruvchilarni qoldirish ham, zanjirni qayta yig'ish ham mumkin. Uch-to'rt bosqichli zanjir — o'qishga qulay. Yetti-sakkiz bosqichli zanjir — ehtimol bir necha nomli qismga bo'linishi kerak.
5. Zanjirning narxi
5.1 Har bosqich — to'liq o'tish va yangi massiv
Zanjirning qulayligi bepul emas. filter → map → reduce uchun kompyuter:
- Butun massivni bir marta aylanadi (
filter) va yangi massiv yasaydi. - O'sha yangi massivni yana aylanadi (
map) va yana bir massiv yasaydi. - Uni uchinchi marta aylanadi (
reduce).
Boshida g'alati tuyulishi mumkin: elementlar konveyerdagi non kabi birma-bir o'tmaydimi? Yo'q. Har stansiya butun partiyani tugatadi, keyingisi shundan keyin boshlaydi. Callback'lar ichiga console.log qo'yib, buni o'z ko'zingiz bilan ko'ring:
Konsolda avval uchala filter, keyin ikkala map yozuvi chiqadi — aralash emas. Bu tartibni «Erta chiqish» bo'limida yana eslaymiz: aynan shu sabab zanjir "uchtasi topildi, yetadi" deb to'xtay olmaydi.
Oddiy sikl esa bitta o'tishda, oraliq massivlarsiz ishlaydi. Farq qanchalik katta? Taxmin qilmaymiz — o'lchaymiz.
5.2 O'lchov: million buyurtma
Million buyurtmali sinov massivini Array.from bilan yasaymiz va to'langanlar summasini uch usulda hisoblaymiz. Har usul to'qqiz marta o'lchandi, grafikda — o'rtadagi (mediana) natija:
- filter → map → reduce3 o'tish, 2 oraliq massiv31,6 ms
- bitta reduce1 o'tish9,4 ms
- for...of1 o'tish11,2 ms
Manba: O'lchov: Node 24.21, Windows 11, performance.now, 9 o'lchovning medianasi, 2026-10-04
Zanjir taxminan uch barobar sekinroq. Lekin raqamlarga diqqat bilan qarang: 31 millisekund — million buyurtma uchun. Xuddi shu o'lchov 1 000 buyurtmada: zanjir 0,03 ms, sikl 0,03 ms. Ko'z ham, foydalanuvchi ham farqni sezmaydi.
O'lchov kodi — sizning kompyuteringizda raqamlar boshqacha chiqadi, lekin nisbat o'xshash bo'ladi:
const buyurtmalar = Array.from({ length: 1_000_000 }, (_, i) => ({
summa: ((i * 7919) % 100000) + 1000,
tolandi: i % 4 !== 0,
}));
const boshi = performance.now();
const tushum = buyurtmalar
.filter((b) => b.tolandi)
.map((b) => b.summa)
.reduce((jami, s) => jami + s, 0);
console.log(tushum, `${(performance.now() - boshi).toFixed(1)} ms`);1_000_000 — pastki chiziq faqat o'qish uchun, son o'sha million (Son yozish shakllari). performance.now — Ko'p elementni samarali chizish darsidagi sekundomer, Node'da ham bor.
5.3 Bosqichlar tartibi
Narxni kamaytirishning eng arzon usuli — tartib. filter darsidagi qoida: avval keraksizini olib tashlang, keyin qolganini ishlang. Million buyurtmaga QQS maydoni qo'shib (map da { ...b, qqs }), to'langanlarini tanlaymiz. Natija bir xil — 750 000 ta buyurtma — lekin vaqt har xil:
| Tartib | map necha marta ishladi |
Vaqt (mediana) |
|---|---|---|
map → filter |
1 000 000 | 131,5 ms |
filter → map |
750 000 | 84,8 ms |
map yangi obyekt yasaydi — bu qimmat ish. Avval filter qilinganda, chorak buyurtma uchun obyekt umuman yasalmadi. Kodni o'zgartirish — ikki qatorni almashtirish. Raqamlar o'sha o'lchovdan: Node 24.21, mediana.
Tekshirib ko'ring: Mijozlar ro'yxatidan faqat Toshkentdagilarning ismlarini katta harf bilan olish kerak. Qaysi tartib yaxshiroq:
.map(ismniKattala).filter(toshkentlikmi)yoki.filter(toshkentlikmi).map(ismniKattala)? Birinchisi ishlaydimi umuman?
Javob
Ikkinchisi. Birinchisi ishlamasligi ham mumkin: map dan keyin elementlar ism satrlari — ularda shahar maydoni yo'q, toshkentlikmi hech narsani topa olmaydi. Avval filter — kerakli maydonlar hali joyida va keraksizlar map gacha olib tashlanadi.
6. Erta chiqish
6.1 Zanjir to'xtamaydi
Bir holatda farq "uch barobar" emas, ming barobar bo'ladi. Jasur aka so'raydi: "100 000 so'mdan katta birinchi uchta buyurtma qaysi?" Zanjir bilan:
const birinchiUchta = buyurtmalar
.filter((b) => b.summa > 100000)
.slice(0, 3);filter "birinchi uchta" haqida hech narsa bilmaydi. U million buyurtmaning hammasini tekshiradi, keyin slice faqat uchtasini oladi. Qolgan ish — behuda.
Sikl esa uchta topilishi bilan to'xtay oladi (break):
const birinchiUchta = [];
for (const b of buyurtmalar) {
if (b.summa > 100000) {
birinchiUchta.push(b);
if (birinchiUchta.length === 3) {
break;
}
}
}Xuddi o'sha million buyurtmada: zanjir — 7,1 ms, sikl — 0,01 ms. Kerakli uchtasi ro'yxat boshida edi — sikl bir necha yuz elementni ko'rib, ishini tugatdi. Erta chiqish (early exit) — natija tayyor bo'lishi bilan qolgan ishni to'xtatish. return va erta qaytish darsidagi g'oyaning sikldagi shakli.
6.2 Erta chiqadigan metodlar
Bitta element yoki ha/yo'q javob kerak bo'lsa, erta chiqadigan metodlar allaqachon bor:
| Savol | Erta chiqmaydi | Erta chiqadi |
|---|---|---|
| "Birinchi mos qaysi?" | filter(...)[0] |
find |
| "Mos bormi?" | filter(...).length > 0 |
some |
| "Hammasi mosmi?" | filter(...).length === n |
every |
filter darsida find va some chaqiruvlarini sanagan edik — ular birinchi javobda to'xtagan edi. "Birinchi N ta" uchun esa tayyor massiv metodi yo'q — sikl va break.
2025-yilda JavaScript'ga "dangasa" zanjir ham qo'shildi — iterator helpers: buyurtmalar.values().filter(...).take(3).toArray(). U elementlarni birma-bir, kerak bo'lgandagina ishlaydi va uchtasi topilishi bilan to'xtaydi. Uni Iterator helpers darsida o'rganamiz — hozir bilish shart emas.
7. Qachon zanjir, qachon sikl
| Vaziyat | Tanlov |
|---|---|
| Odatdagi ro'yxat (yuzlab, minglab element) | zanjir — o'qiluvchanlik muhimroq |
| Bitta element yoki ha/yo'q kerak | find, some, every |
| "Birinchi N ta", natija topilishi bilan to'xtash | for...of + break |
| Bir o'tishda bir nechta natija (yig'indi va soni va eng kattasi) | for...of yoki bitta reduce |
| Juda katta ma'lumot (yuz minglab) va o'lchov sekinlikni ko'rsatdi | bitta o'tishli sikl |
Asosiy qoida: avval o'qiluvchan yozing, keyin o'lchang, keyin — kerak bo'lsa — tezlashtiring. "Sikl tezroq" deb har zanjirni siklga aylantirish — o'qiluvchanlikni hech kim sezmaydigan millisekundga almashtirish. Sekinlik bo'lsa, u ko'pincha zanjirda emas, boshqa joyda — buni bugungi «Vazifalar qadami» da ko'rasiz.
8. Ko'p uchraydigan xatolar
8.1 forEach zanjir o'rtasida
«Massiv qaytarmaydigan metodlar» bo'limi: TypeError: Cannot read properties of undefined (reading 'map'). Tuzatish: forEach ni oxirga qo'ying yoki map ishlating.
8.2 Zanjir boshida sort
«sort zanjirda» bo'limi: kirish massivi o'zgaradi, xato xabari yo'q. Tuzatish: toSorted.
8.3 map dan keyin kerakli maydon yo'qoladi
buyurtmalar.map((b) => b.summa).filter((b) => b.tolandi) — summa sonlarida tolandi yo'q, filter bo'sh massiv qaytaradi. Xato xabari yo'q, natija — []. Tuzatish: avval filter, keyin map.
8.4 Zanjir o'rtasidagi reduce boshlang'ich qiymatsiz
Bo'sh massiv filter dan keyin juda tez paydo bo'ladi: bugun hech kim to'lamagan bo'lsa, filter [] qaytaradi. Keyingi reduce((a, s) => a + s) — TypeError: Reduce of empty array with no initial value (reduce). Tuzatish: zanjirdagi reduce ga doim boshlang'ich qiymat.
8.5 Juda uzun zanjir
O'n bosqichli, har birida uch qatorli callback'li zanjirni hech kim bir qarashda o'qiy olmaydi. Tuzatish: callback'larni nomli funksiyalarga chiqaring, zanjirni ma'noli bo'laklarga bo'lib, oraliq natijalarga nom bering.
9. Mashqlar
1-mashq (oson): O'tganlar ro'yxati
Imtihondan o'tganlarning (ball ≥ 60) ismlarini o'zbek alifbosi tartibida, vergul bilan chiqaring. Bitta zanjir: filter → map → toSorted → join.
const talabalar = [
{ ism: "Shuhrat", ball: 78 },
{ ism: "Olim", ball: 54 },
{ ism: "O'tkir", ball: 91 },
{ ism: "Aziz", ball: 60 },
];Yechim
const talabalar = [
{ ism: "Shuhrat", ball: 78 },
{ ism: "Olim", ball: 54 },
{ ism: "O'tkir", ball: 91 },
{ ism: "Aziz", ball: 60 },
];
const otganlar = talabalar
.filter((t) => t.ball >= 60)
.map((t) => t.ism)
.toSorted((a, b) => a.localeCompare(b, "uz"))
.join(", ");
console.log(otganlar); // Aziz, O'tkir, ShuhratTo'rt bosqich: tanla, ismini ol, sarala, ula. join satr qaytaradi — zanjirning oxiri. localeCompare(…, "uz") — "O'tkir" z dan keyingi o' harfi bilan, shuning uchun "Shuhrat" dan oldin, lekin "Aziz" dan keyin (sort).
2-mashq (o'rta): Taksi: qimmat safarlarning o'rtachasi
30 000 so'mdan qimmat safarlarning o'rtacha narxini toping. Bunday safar bo'lmasa — 0 chiqsin, NaN emas.
Ishora: zanjir bilan narxlarni oling, o'rtacha uchun yig'indini uzunlikka bo'ling — bo'sh massivni alohida tekshiring.
const safarlar = [
{ narx: 25000 },
{ narx: 38000 },
{ narx: 52000 },
{ narx: 18000 },
];Yechim
function qimmatlarOrtachasi(safarlar) {
const narxlar = safarlar
.map((s) => s.narx)
.filter((narx) => narx > 30000);
if (narxlar.length === 0) {
return 0;
}
return narxlar.reduce((jami, n) => jami + n, 0) / narxlar.length;
}
const safarlar = [
{ narx: 25000 },
{ narx: 38000 },
{ narx: 52000 },
{ narx: 18000 },
];
console.log(qimmatlarOrtachasi(safarlar)); // 45000
console.log(qimmatlarOrtachasi([])); // 0Bu yerda map filter dan oldin — va bu to'g'ri: filtr narxning o'ziga qaraydi, obyektning boshqa maydoni kerak emas. Bosqichlar tartibi qoidasi "qimmat ishni keyinga qoldir" degani; bu map esa arzon — maydonni olish xolos. Zanjir o'rtacha uchun ikki marta kerak bo'lgan massivda to'xtadi — shuning uchun oraliq nom (narxlar) bor. Bo'sh massivda 0 / 0 — NaN bo'lardi, erta return 0 buni oldini oldi.
3-mashq (qiyin): Kunlik hisobot — eng ko'p tushum bergan ikki taom
Buyurtmalardan har taomning jami tushumini hisoblang va eng ko'p tushum bergan ikkita taomni osh — 105000 so'm ko'rinishida chiqaring. Pipeline bosqichlari:
Object.groupBy— taom bo'yicha (Guruhlash).Object.entries→map— har taom uchun{ taom, tushum }.toSorted— tushum kamayishi bo'yicha.slice(0, 2)→map— satrga.
const buyurtmalar = [
{ taom: "osh", summa: 35000 },
{ taom: "choy", summa: 5000 },
{ taom: "osh", summa: 70000 },
{ taom: "manti", summa: 60000 },
{ taom: "choy", summa: 10000 },
];Yechim
const buyurtmalar = [
{ taom: "osh", summa: 35000 },
{ taom: "choy", summa: 5000 },
{ taom: "osh", summa: 70000 },
{ taom: "manti", summa: 60000 },
{ taom: "choy", summa: 10000 },
];
const qosh = (jami, b) => jami + b.summa;
const taomlar = Object.groupBy(buyurtmalar, (b) => b.taom);
const hisobot = Object.entries(taomlar)
.map(([taom, royxat]) => ({ taom, tushum: royxat.reduce(qosh, 0) }))
.toSorted((a, b) => b.tushum - a.tushum)
.slice(0, 2)
.map((q) => `${q.taom} — ${q.tushum} so'm`);
console.log(hisobot.join("\n"));Konsolda:
osh — 105000 so'm
manti — 60000 so'mBesh bosqichli pipeline: guruhla, yig', sarala, kes, yoz. Har bosqich bitta ish qiladi, kirish massivi o'zgarmadi. \n — yangi qator (Template literals). toSorted o'rnida sort ham xavfsiz edi — u map yasagan oraliq massivni tartiblardi. Lekin toSorted bu haqda o'ylashni talab qilmaydi.
4-mashq: Vazifalar qadami — oqimni o'lchash va hujjatlashtirish
So'nggi besh darsda vazifalar da ma'lumot oqimi shakllandi: holat → filter → toSorted → map(qatorYasa) → ekran, yonida esa groupBy → hisob. Bu — pipeline. Uni katta ma'lumotda o'lchaymiz va README'da hujjatlashtiramiz.
- Yangi branch:
git switch -c chore/malumot-oqimi. - Brauzerda
vazifalarni oching.flat,fillvaArray.fromdarsidagikurs/mashqlar/10/07-sinov/sinov-vazifalar.jsdan foydalanib, konsolda 10 000 ta vazifa yasang. korinadiganlar,statistikavarendervaqtini alohida o'lchang. Qaysi biri sekin?- Natijaga qarab qaror qiling: zanjirni siklga aylantirish kerakmi?
- README'ga "Ma'lumot oqimi" bo'limini yozing.
Yechim
Konsolga (sinov-vazifalar.js dagi kod, faqat length — 10 000):
holat.vazifalar = Array.from({ length: 10000 }, (_, i) => ({
id: i + 1,
matn: `Sinov vazifasi ${i + 1}`,
bajarildi: i % 3 === 0,
}));
holat.keyingiId = 10001;
function olch(nom, ish) {
const boshi = performance.now();
ish();
console.log(`${nom}: ${(performance.now() - boshi).toFixed(1)} ms`);
}
olch("korinadiganlar", korinadiganlar);
olch("statistika", statistika);
olch("render", render);Biz Chrome 154 da olgan natija (sizda raqamlar boshqacha bo'ladi):
korinadiganlar: 2.1 ms
statistika: 1.7 ms
render: 104.3 msBu o'lchov darsning eng muhim xulosasini ko'rsatadi:
- Zanjir sekin emas.
filter+toSorted10 000 vazifada — 2 millisekund.groupBy— undan ham kam. - Sekin joy — DOM.
rendervaqtining 95 foizdan ko'piqatorYasa10 000 tali, katak, yorliq va tugma yasashiga va brauzer ularni joylashtirishiga ketdi.renderichidagi zanjir esa o'sha 2 ms. - Qaror. Zanjirni siklga aylantirish 2 ms dan 1 ms ga tushirardi — 104 ms ning yonida bu hech narsa. O'qiluvchan kod qoladi. Haqiqatan 10 000 vazifa kerak bo'lsa, yechim boshqa: faqat ekranda ko'rinadigan qatorlarni chizish — Uzun ro'yxatlar: virtualizatsiya darsida ko'ramiz. Oddiy foydalanuvchida esa o'nlab vazifa bo'ladi.
Ko'p elementni samarali chizish darsidagi qoida tasdiqlandi: taxmin emas, o'lchov. Agar "sikl tezroq" degan gapga ishonib zanjirni buzganimizda, ilova sezilarli tezlashmasdi.
README'ga qo'shing:
## Ma'lumot oqimi
Holat (`holat`) — yagona haqiqat manbai. Ekran har safar undan
qayta hisoblanadi, `holat.vazifalar` ning o'zi tartiblanmaydi:
- ro'yxat: `filter(mosmi)` → `toSorted(faollarOldin)` →
`map(qatorYasa)` → `replaceChildren`
- hisob: `Object.groupBy(guruhNomi)` → "N ta vazifa qoldi,
M ta bajarildi"
O'lchov (Chrome, 10 000 vazifa): zanjirlar ~2 ms, DOM — ~100 ms.Commit, merge va push — HOF modulining (10-qism, 1–9-darslar) yakuni:
git add README.md
git commit -m "Docs: ma'lumot oqimi va o'lchov natijasi"
git switch main
git merge chore/malumot-oqimi
git branch -d chore/malumot-oqimi
git pushSahifani yangilang — sinov vazifalari yo'qoladi, ilova boshlang'ich uch vazifaga qaytadi. Kodda o'zgarish yo'q: bu qadam faqat o'lchov va hujjat.
To'qqiz darsda vazifalar.js da nima o'zgardi:
| Dars | O'zgarish | Turi |
|---|---|---|
| Callback imzosi | filtr tugmalari — forEach |
refaktoring |
map |
qatorYasa + map |
refaktoring |
filter |
korinadiganlar — filter |
refaktoring |
reduce |
faollarSoni — reduce |
refaktoring |
sort |
bajarilmaganlar tepada | yangi imkoniyat |
| Nusxa bilan o'zgartirish | toSorted, toSpliced |
refaktoring |
Array.from |
500 ta sinov vazifasi (konsolda) | sinov |
| Guruhlash | statistika() (faollarSoni o'rniga): hisobda bajarilganlar soni ham |
yangi imkoniyat |
| shu dars | ma'lumot oqimi o'lchandi va hujjatlandi | hujjat |
10. Real ishda
- Ma'lumotni tayyorlash. Serverdan kelgan ro'yxatni ekranga tayyorlash — deyarli har doim zanjir: keraksizini olib tashla, sarala, kerakli ko'rinishga aylantir. React komponentlarida
vazifalar.filter(...).map((v) => <li>…</li>)— har kuni yoziladigan qator (17-qism). - Hisobotlar va tahlil. "Bu oy, to'langan, Toshkentdagi buyurtmalarning o'rtacha summasi" —
filter→filter→map→reduce. Data Science'dagi jadval kutubxonalari (masalan Python'dagi pandas) ham aynan shunday zanjir uslubida ishlaydi. - Performans. Tajribali dasturchi "sikl tezroq" deb darhol qayta yozmaydi — avval profil qiladi. Bugungi «Vazifalar qadami» dagi natija — sekinlik zanjirda emas, DOM'da — real loyihalarda juda ko'p uchraydi.
- Kod ko'rib chiqish. Uzun, nomsiz callback'li zanjir va
sortbilan boshlanadigan zanjir — tez-tez qaytariladigan kod. Nomli bosqichlar vatoSorted— "toza kod" belgisi. - Intervyu. "Bu zanjir necha marta aylanadi?", "nega
filter→map, teskarisi emas?", "filter(...)[0]o'rniga nima yozasiz?" — javoblar: har bosqich bir marta; keraksizini avval olib tashlash;find.
Xulosa
- Massiv qaytaradigan metodlar zanjirga ulanadi: har bosqich oldingisining natijasini oladi — bu pipeline.
- Har metod alohida qatorda, nuqta bilan; murakkab callback — nomli funksiya (
tolanganmi,summasi). - Zanjir
forEach,find,some,joinva boshlang'ich qiymatlireduceda tugaydi. "Cannot read properties of undefined (reading 'X')" — X dan oldingi bosqichni tekshiring. - Zanjir boshida
sortemas,toSorted. Avvalfilter, keyinmap. - Har bosqich — to'liq o'tish va yangi massiv: millionda ~3 barobar sekinroq, mingda — farq yo'q.
- Birinchi topilgani yetarli bo'lsa —
find/someyokifor...of+break. Avval o'qiluvchan yozing, keyin o'lchang.
Keyingi dars: Massivga o'xshash obyektlar va teshikli massivlar — NodeList va { length: n } kabi "massivga o'xshash" narsalar, teshiklar va ular metodlarda qanday kutilmagan xulq ko'rsatishi.
Manbalar
- MDN: "Array" — "Iterative methods", "Array.prototype.find()", "Iterator.prototype.take()" — developer.mozilla.org
- MDN: "Performance: now() method" — developer.mozilla.org
- O'lchovlar: Node 24.21 va Chrome 154, Windows 11, 2026-10-04 (kurs muallifi kompyuteri)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!