Mundarija (37)
- Bu darsda
- 1. Nega bu kerak?
- 2. flat — tekislash
- 2.1 Bir qavat
- 2.2 Chuqurlik
- 2.3 Teshiklar yo'qoladi
- 3. flatMap — aylantirib, tekislash
- 3.1 map + flat
- 3.2 flatMap ichidan
- 3.3 Bir elementdan nol yoki bir nechta
- 3.4 Faqat bir qavat
- 4. fill — to'ldirish
- 4.1 Bir qiymat bilan
- 4.2 Tuzoq: obyekt bilan to'ldirish
- 5. Array.from — istalgan narsadan massiv
- 5.1 Ro'yxatga o'xshash narsalardan
- 5.2 Ikkinchi argument — aylantiruvchi
- 5.3 { length: n } — noldan massiv yasash
- 5.4 Diapazon
- 5.5 To'g'ri jadval: har o'ringa alohida massiv
- 5.6 Array.from va spread farqi
- 6. copyWithin — massiv ichida ko'chirish
- 7. Umumiy jadval
- 8. Ko'p uchraydigan xatolar
- 8.1 fill bilan obyekt yoki massiv
- 8.2 Bo'sh massivda map
- 8.3 Chuqurlikni unutish
- 8.4 flatMap dan chuqur tekislashni kutish
- 8.5 new Array ga bitta son yoki bitta satr
- 9. Mashqlar
- 1-mashq (oson): Hafta kunlari
- 2-mashq (o'rta): Oshxona uchun porsiyalar
- 3-mashq (qiyin): Zal sxemasi
- 4-mashq: Vazifalar qadami — yuzlab sinov vazifasi
- 10. Real ishda
- Xulosa
- Manbalar
JavaScript flat, flatMap, fill va Array.from: massivni tekislash va yasash
Qisqacha:
flatichma-ich massivlarni bitta tekis massivga ochadi (flat(2)— ikki qavat).flatMap—mapva bir qavatflatbirgalikda. U har elementdan bir nechta yoki nol element chiqara oladi.fillmassivni bitta qiymat bilan to'ldiradi (aslini o'zgartiradi).Array.fromistalgan ro'yxatdan massiv yasaydi:Array.from({ length: 5 }, (_, i) => i + 1)—[1, 2, 3, 4, 5].
Bu darsda
flatbilan ichma-ich massivni kerakli chuqurlikkacha tekislay olasiz.flatMapbilan bitta elementdan bir nechta (yoki nol) element yasay olasiz.fillbilan massiv to'ldira olasiz va uning obyekt bilan tuzog'ini bilasiz.Array.frombilan satr,NodeListva{ length: n }dan massiv, diapazon va jadval yasay olasiz.vazifalarni yuzlab sinov vazifasi bilan tekshirasiz.
Oldin bilishingiz kerak: Kesish, birlashtirish va matnga aylantirish, map, filter, Sayoz va chuqur nusxalash, Nusxa bilan o'zgartirish.
1. Nega bu kerak?
«Bahor» da kechqurun uch stol buyurtma berdi. Otabek har stolning buyurtmasini alohida ro'yxatda yozdi:
const stollar = [["osh", "choy"], ["manti"], ["lag'mon", "choy"]];Rustam aka oshxonada bitta tekis ro'yxatni ko'rmoqchi: nima pishirish kerak? Stollar bo'yicha bo'linish unga kerak emas. Bu — tekislash masalasi.
Jasur aka esa yangi hafta jadvalini tuzmoqchi: 7 kun, har kunga bo'sh ro'yxat. Yoki ish soatlari: 7 dan 22 gacha har soat uchun bitta katak. Bu yerda massiv hali yo'q — uni noldan yasash kerak. Qo'lda [7, 8, 9, …, 22] deb yozish zerikarli va xatoga moyil.
Bugungi to'rt vosita shu ikki ish uchun: ichma-ich massivni ochish va massivni yasash/to'ldirish. flat bilan Kesish va birlashtirish darsida qisqa tanishgan edik, Array.from bilan esa satrni harflarga bo'lganmiz. O'sha darslarda "boshqa imkoniyatlari keyinroq" degan edik — mana o'sha "keyinroq".
Hayotdan o'xshatish: posilka. Katta qutini ochasiz — ichida yana qutilar, ba'zilarining ichida yana kichikroqlari. flat — qutilarni ochib, ichidagi narsalarni bitta stolga to'kish. Necha qavat ochishni o'zingiz aytasiz.
2. flat — tekislash
2.1 Bir qavat
const stollar = [["osh", "choy"], ["manti"], ["lag'mon", "choy"]];
console.log(stollar.flat());
// [ 'osh', 'choy', 'manti', "lag'mon", 'choy' ]Uchta ichki massiv ochildi, elementlari bitta yangi massivga tushdi. stollar o'zgarmadi — flat yangi massiv qaytaradi.
"Choy" ikki marta turibdi — ikki stol choy so'ragan. flat takrorlarni olib tashlamaydi, u faqat qavslarni ochadi. Har taomni bir martadan qoldirish kerak bo'lsa, filter darsidagi indexOf usuli yoki keyinroq o'rganadigan Set kerak bo'ladi.
Kesish va birlashtirish darsida xuddi shu natijani concat va spread bilan olgan edik: [].concat(...stollar). U ham bir qavat ochadi, lekin o'qishga og'irroq va chuqurlik bera olmaysiz. Bugun ichma-ich ro'yxatni ochish uchun asosiy vosita — flat.
2.2 Chuqurlik
Uchinchi stol "lag'mon va yana alohida ichimliklar ro'yxati" deb yozilgan bo'lsa-chi?
const stollar = [["osh"], ["lag'mon", ["choy", "non"]]];
console.log(stollar.flat());
// [ 'osh', "lag'mon", [ 'choy', 'non' ] ]
console.log(stollar.flat(2));
// [ 'osh', "lag'mon", 'choy', 'non' ]flat() — argumentsiz — faqat bir qavatni ochadi: ichki-ichki massiv joyida qoldi. flat(2) — ikki qavat. Argument — chuqurlik (depth): necha qavat qutini ochish.
Necha qavat ekani noma'lum bo'lsa — Infinity (cheksizlik): "oxirigacha och".
const daraxt = [1, [2, [3, [4]]]];
console.log(daraxt.flat(Infinity)); // [ 1, 2, 3, 4 ]Sxemada har qavat — bitta flat qadami. Strelkalarga qarang: har qadamda bitta qavat qavslar yo'qoladi.
flowchart LR
A["[1, [2, [3, [4]]]]"] -- "flat(1)" --> B["[1, 2, [3, [4]]]"]
B -- "flat(1)" --> C["[1, 2, 3, [4]]"]
C -- "flat(1)" --> D["[1, 2, 3, 4]"]flat(3) — uchala qadam birdan. flat(Infinity) — qavat qolmaguncha.
2.3 Teshiklar yo'qoladi
flat yana bir ish qiladi: massivdagi bo'sh o'rinlarni ("teshiklarni") tashlab yuboradi:
const sonlar = [1, , 3, [4, , 6]];
console.log(sonlar.flat()); // [ 1, 3, 4, 6 ]Ikki vergul orasidagi bo'sh joy — teshik. Bunday massivlar va ularning g'alati xulqi — Massivga o'xshash obyektlar va teshikli massivlar darsida. Hozircha bilib qo'ying: flat teshiklarni ko'chirmaydi.
Tekshirib ko'ring:
[["a"], [["b"]], "c"].flat()nima qaytaradi?
Javob
[ 'a', [ 'b' ], 'c' ]. Bir qavat ochildi: ["a"] dan "a" chiqdi, [["b"]] dan — ["b"] (yana massiv). "c" massiv emas — o'zgarishsiz o'tdi. flat(2) bo'lsa — [ 'a', 'b', 'c' ].
3. flatMap — aylantirib, tekislash
3.1 map + flat
Buyurtmalar obyekt ko'rinishida kelsa, avval taomlar ro'yxatini olish kerak:
const buyurtmalar = [
{ stol: 1, taomlar: ["osh", "choy"] },
{ stol: 2, taomlar: ["manti"] },
];
console.log(buyurtmalar.map((b) => b.taomlar));
// [ [ 'osh', 'choy' ], [ 'manti' ] ]
console.log(buyurtmalar.flatMap((b) => b.taomlar));
// [ 'osh', 'choy', 'manti' ]map har buyurtmadan massiv qaytardi — natija massivlar massivi. flatMap esa xuddi shu callback natijalarini darhol bir qavat tekisladi. Ya'ni flatMap(f) — map(f).flat() ning qisqa va bir o'tishli shakli. Callback imzosi ham map niki: (element, index, array).
3.2 flatMap ichidan
Soddalashtirilgan nusxa — map dagi siklning o'zi, faqat natijani push(...) bilan "to'kib" qo'shamiz:
function aylantirTekisla(massiv, amal) {
const natija = [];
for (let i = 0; i < massiv.length; i++) {
const qiymat = amal(massiv[i], i, massiv);
if (Array.isArray(qiymat)) {
natija.push(...qiymat); // massiv bo'lsa — ichini to'k
} else {
natija.push(qiymat); // massiv bo'lmasa — o'zini qo'sh
}
}
return natija;
}
const stollar = [
{ taomlar: ["osh", "choy"] },
{ taomlar: ["manti"] },
];
console.log(aylantirTekisla(stollar, (s) => s.taomlar));
// [ 'osh', 'choy', 'manti' ]Array.isArray — "bu massivmi?" (Kesish va birlashtirish). push(...qiymat) — spread bilan har elementni alohida qo'shish (Spread). Callback massiv qaytarsa, uning ichi natijaga tushadi; massiv bo'lmasa — o'zi.
3.3 Bir elementdan nol yoki bir nechta
Shu xulqdan flatMap ning eng foydali hiylasi chiqadi. Callback [] qaytarsa — natijaga hech narsa tushmaydi. [x] qaytarsa — bitta element. [x, y] — ikkita. Demak flatMap bir vaqtda ham tanlaydi, ham aylantiradi.
Mijozlar izoh maydoniga stol raqamini yozgan, ba'zilari esa xato yozgan:
const yozilgan = ["12", "beshinchi", "7", ""];
const raqamlar = yozilgan.flatMap((s) => {
const raqam = Number(s);
return s !== "" && !Number.isNaN(raqam) ? [raqam] : [];
});
console.log(raqamlar); // [ 12, 7 ]Callback'dagi shart ikki qismli: satr bo'sh emas va undan son chiqdi. Ikkalasi rost bo'lsa — [raqam], aks holda — []. Bo'sh satr nega alohida tekshiriladi? Chunki Number("") — NaN emas, 0 (Matn ↔ son). Tekshirmasak, bo'sh izoh "0-stol" bo'lib qolardi.
To'g'ri satrlar son bo'lib [raqam] ichida qaytdi va natijaga tushdi. "beshinchi" va bo'sh satr [] qaytardi va g'oyib bo'ldi. filter + map zanjirida Number ni ikki marta chaqirish kerak bo'lardi: bir marta tekshirish, bir marta aylantirish uchun. flatMap da — bir marta.
Teskarisi — bitta elementdan bir nechta. Sharhdagi teglar vergul bilan yozilgan, bizga barcha teglarning tekis ro'yxati kerak:
const sharhlar = ["mazali, arzon", "tez", "mazali, toza"];
const teglar = sharhlar.flatMap((s) => s.split(", "));
console.log(teglar); // [ 'mazali', 'arzon', 'tez', 'mazali', 'toza' ]Har sharh split bilan massivga aylandi (Kesish, bo'lish va to'ldirish), flatMap esa ularni bitta ro'yxatga yig'di.
3.4 Faqat bir qavat
flatMap ning flat qismi doim bir qavat — chuqurlik argumenti yo'q:
const natija = [[1, [2]], [3]].flatMap((x) => x);
console.log(natija); // [ 1, [ 2 ], 3 ]Callback qaytargan massivlar ochildi, lekin ularning ichidagi [2] qoldi. Chuqurroq kerak bo'lsa — map(...).flat(2).
Tekshirib ko'ring:
[1, 2, 3].flatMap((x) => (x === 2 ? [] : [x, x]))nima qaytaradi?
Javob
[ 1, 1, 3, 3 ]. 1 va 3 uchun callback ikki elementli massiv qaytardi — har biri ikki marta tushdi. 2 uchun — [], u natijadan butunlay chiqib ketdi. Bitta flatMap ham filter, ham "ko'paytirish" ishini qildi.
4. fill — to'ldirish
4.1 Bir qiymat bilan
const ballar = new Array(5).fill(0);
console.log(ballar); // [ 0, 0, 0, 0, 0 ]new Array(5) — 5 ta bo'sh o'rinli massiv yasaydi. new so'zini Konstruktor funksiya darsida o'rganamiz — hozir "5 o'rinli yangi massiv" deb o'qing. fill(0) har o'ringa 0 yozdi.
fill ning yana ikki ixtiyoriy argumenti bor — qayerdan va qayergacha (oxiri kirmaydi, xuddi slice dagidek):
const kunlar = ["bo'sh", "bo'sh", "bo'sh", "bo'sh", "bo'sh"];
kunlar.fill("band", 1, 3);
console.log(kunlar); // [ "bo'sh", 'band', 'band', "bo'sh", "bo'sh" ]E'tibor bering: fill asl massivni o'zgartiradi va o'shani qaytaradi — xuddi sort kabi. Nusxa kerak bo'lsa — avval [...kunlar]. toFilled degan nusxa metodi esa yo'q: Nusxa bilan o'zgartirish darsidagi to'rt metod faqat sort, reverse, splice va tayinlash uchun qo'shilgan.
Odatda fill ni ikki holatda ishlatishadi. Birinchisi — yangi massivni boshlang'ich qiymat bilan tayyorlash: new Array(7).fill(0) — haftaning har kuni uchun nol so'm tushum. Ikkinchisi — mavjud massivning bir qismini "tozalash": hafta oxirida jadval.fill("bo'sh"). Ikkalasida ham qiymat son yoki satr — keyingi bo'limdagi tuzoq aynan shu shart buzilganda chiqadi.
Tekshirib ko'ring:
const a = [1, 2, 3]; const b = a.fill(9);dan keyinanima vaa === bnima beradi?
Javob
a — [ 9, 9, 9 ], a === b — true. fill asl massivning hamma o'rniga 9 yozdi va o'sha massivni qaytardi. b — yangi massiv emas, a ning ikkinchi nomi.
4.2 Tuzoq: obyekt bilan to'ldirish
Jasur aka uch stol uchun bo'sh buyurtma ro'yxatlarini tayyorlaydi va birinchi stolga osh yozadi:
const stollar = new Array(3).fill([]);
stollar[0].push("osh");
console.log(stollar); // [ [ 'osh' ], [ 'osh' ], [ 'osh' ] ]Osh uchala stolga ham tushdi! fill([]) bitta [] yasadi va o'sha bitta massivning havolasini uch o'ringa yozdi (Havola semantikasi). Sxemadagi strelkalarga qarang — uchtasi bitta qutiga qaraydi:
flowchart LR
S0["stollar[0]"] --> M["bitta massiv: ['osh']"]
S1["stollar[1]"] --> M
S2["stollar[2]"] --> MSonlar va satrlar bilan bu muammo yo'q — ular nusxalanadi. Obyekt yoki massiv bilan esa fill doim "bitta narsani hamma joyga" qo'yadi. Har o'ringa alohida massiv kerak bo'lsa — keyingi bo'limdagi Array.from.
Diqqat:
new Array(n).fill([])vanew Array(n).fill({})— internetdagi ko'p kodda uchraydigan xato. Xato xabari chiqmaydi: dastur faqat "nega hammasi birga o'zgaryapti?" degan savolga olib keladi.
5. Array.from — istalgan narsadan massiv
5.1 Ro'yxatga o'xshash narsalardan
Array.from(x) — "x dan massiv yasa". Kesish va birlashtirish darsida satrni harflarga bo'lgan edik:
console.log(Array.from("salom")); // [ 's', 'a', 'l', 'o', 'm' ]Array.from for...of bilan aylanib chiqsa bo'ladigan har narsani qabul qiladi: satr, massiv, NodeList, keyinroq o'rganadigan Set va Map. Bunday narsalar iterable deb ataladi — ularning ichki mexanizmini Iteratsiya protokoli darsida o'rganamiz, hozir bilish shart emas.
Brauzerda eng ko'p uchraydigan holat — querySelectorAll natijasi. NodeList da forEach bor, lekin map va filter yo'q (map darsidagi xato):
const tugmalar = document.querySelectorAll("[data-filtr]");
const nomlar = Array.from(tugmalar).map((t) => t.dataset.filtr);
console.log(nomlar.join(", ")); // hammasi, faol, bajarilganArray.from NodeList dan oddiy massiv yasadi — endi barcha massiv metodlari ishlaydi. [...tugmalar] ham xuddi shu ishni qiladi.
5.2 Ikkinchi argument — aylantiruvchi
Array.from ikkinchi argument sifatida map callback'ini oladi:
console.log(Array.from("osh", (harf) => harf.toUpperCase()));
// [ 'O', 'S', 'H' ]Bu Array.from(x).map(f) bilan bir xil natija beradi, lekin oraliq massivsiz — bitta o'tishda. Callback imzosi: (element, index).
5.3 { length: n } — noldan massiv yasash
Endi eng kuchli hiyla. Array.from ga length xususiyati bor oddiy obyekt bersangiz, u shuncha o'rinli massiv yasaydi:
console.log(Array.from({ length: 3 }));
// [ undefined, undefined, undefined ]{ length: 3 } — "uzunligi 3 ga teng" degan obyekt, ichida boshqa hech narsa yo'q. Array.from 0, 1, 2 indekslarini so'radi va har safar undefined oldi. Bunday "uzunligi bor, lekin massiv emas" obyektlar massivga o'xshash obyektlar deb ataladi — ular Massivga o'xshash obyektlar darsining mavzusi.
Bu undefined larning o'zi kerak emas. Foydasi ikkinchi argumentda: callback indeksni oladi va har o'rinni hisoblab beradi. Keyingi tugmasini bosib, stol nomlari qanday yasalishini kuzating:
Birinchi parametr — _: element kerak emas, lekin indeks ikkinchi o'rinda (Callback imzosi darsidagi kelishuv).
5.4 Diapazon
Diapazon (range) — ketma-ket sonlar ro'yxati: 1 dan 5 gacha, 7 dan 22 gacha. Ko'p tillarda buning uchun alohida funksiya bor, JavaScript'da esa — Array.from:
const birdanBeshgacha = Array.from({ length: 5 }, (_, i) => i + 1);
console.log(birdanBeshgacha); // [ 1, 2, 3, 4, 5 ]
const soatlar = Array.from({ length: 16 }, (_, i) => 7 + i);
console.log(soatlar.join(" "));
// 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22«Bahor» 7:00 dan 23:00 gacha ishlaydi. Oxirgi soatlik katak 22:00 dan 23:00 gacha — shuning uchun 7 dan 22 gacha 16 ta son. Formula: boshi + i, uzunligi esa oxiri - boshi + 1.
5.5 To'g'ri jadval: har o'ringa alohida massiv
«fill — to'ldirish» bo'limidagi stollar muammosi Array.from bilan hal bo'ladi:
const stollar = Array.from({ length: 3 }, () => []);
stollar[0].push("osh");
console.log(stollar); // [ [ 'osh' ], [], [] ]Farq qayerda? fill([]) da [] bir marta hisoblandi. Array.from da esa callback har o'rin uchun qaytadan chaqiriladi — har safar yangi []. Uch o'rin — uch xil massiv.
5.6 Array.from va spread farqi
[...x] va Array.from(x) ko'pincha bir xil ish qiladi: satrdan, NodeList dan massiv yasaydi. Lekin { length: 3 } bilan farq ko'rinadi:
const uch = { length: 3 };
console.log([...uch]);TypeError: uch is not iterableTarjimasi: "uch — iterable emas", ya'ni uni for...of bilan aylanib bo'lmaydi. Spread faqat iterable bilan ishlaydi. { length: 3 } esa iterable emas — u faqat "uzunligim 3" deydi. Array.from ikkala turni ham qabul qiladi: avval "iterable'mi?" deb so'raydi, bo'lmasa length ga qarab indekslarni birma-bir oladi.
Xabarda o'zgaruvchi nomi ko'rsatilgani foydali: qaysi qiymat aybdor ekanini darhol bilasiz. O'zgaruvchisiz yozilsa ([...{ length: 3 }]), Node nom o'rniga {(intermediate value)} — "oraliq qiymat" deb yozadi. Qoida: spread — tayyor ro'yxatlar uchun, Array.from — { length: n } va aylantiruvchi callback kerak bo'lganda.
Tekshirib ko'ring:
Array.from({ length: 4 }, (_, i) => i * 10)nima qaytaradi?new Array(4).fill(0).map((_, i) => i * 10)-chi?
Javob
Ikkalasi ham [ 0, 10, 20, 30 ]. Ikkinchisida avval fill(0) teshiklarni to'ldiradi, keyin map indeks bo'yicha aylantiradi. Birinchisi qisqaroq va bitta o'tishda. fill siz new Array(4).map(...) esa ishlamaydi — «Ko'p uchraydigan xatolar» bo'limida ko'ramiz.
6. copyWithin — massiv ichida ko'chirish
Kam uchraydigan, lekin bilib qo'yish kerak bo'lgan metod. copyWithin(qayerga, qayerdan, qayergacha) massivning bir qismini o'sha massivning boshqa joyiga ko'chiradi:
const sonlar = [1, 2, 3, 4, 5];
sonlar.copyWithin(0, 3);
console.log(sonlar); // [ 4, 5, 3, 4, 5 ]3-indeksdan oxirigacha (4, 5) olindi va 0-indeksdan boshlab ustiga yozildi. Uzunlik o'zgarmaydi. U ham asl massivni o'zgartiradi. Oddiy ilovalarda deyarli kerak bo'lmaydi; asosiy ishi — baytlar bilan ishlash, Typed arrays darsida.
7. Umumiy jadval
| Metod | Asl massiv | Nima qaytaradi |
|---|---|---|
flat(chuqurlik) |
o'zgarmaydi | yangi, tekislangan massiv |
flatMap(f) |
o'zgarmaydi | yangi massiv: map(f).flat() |
fill(qiymat, boshi, oxiri) |
o'zgaradi | o'sha massiv |
copyWithin(qayerga, boshi, oxiri) |
o'zgaradi | o'sha massiv |
Array.from(x, f) |
— | yangi massiv |
Array.from massiv metodi emas, Array ning o'zining funksiyasi: Array.from(...) deb chaqiriladi, [].from emas. Shuning uchun "asl massiv" ustuni unga tegishli emas.
8. Ko'p uchraydigan xatolar
8.1 fill bilan obyekt yoki massiv
«Tuzoq: obyekt bilan to'ldirish» bo'limi: new Array(3).fill([]) — uch o'rinda bitta massiv. Tuzatish: Array.from({ length: 3 }, () => []).
8.2 Bo'sh massivda map
const stollar = new Array(3).map((_, i) => `${i + 1}-stol`);
console.log(stollar); // [ <3 empty items> ]map teshiklarni o'tkazib yuboradi — callback bir marta ham chaqirilmadi. new Array(3) uchta bo'sh o'rin yasaydi, undefined lar emas. Tuzatish: Array.from({ length: 3 }, (_, i) => ...).
8.3 Chuqurlikni unutish
[1, [2, [3]]].flat() — [ 1, 2, [ 3 ] ], to'liq tekis emas. Xato xabari yo'q — faqat keyingi kod massiv o'rniga son kutib qoqiladi. Tuzatish: chuqurlikni bilsangiz — flat(2), bilmasangiz — flat(Infinity).
8.4 flatMap dan chuqur tekislashni kutish
«Faqat bir qavat» bo'limi. flatMap doim bir qavat ochadi. Tuzatish: map(...).flat(Infinity).
8.5 new Array ga bitta son yoki bitta satr
console.log(new Array(3)); // [ <3 empty items> ]
console.log(new Array("3")); // [ '3' ]Bitta son argument — uzunlik. Boshqa har qanday bitta argument — element. Bu g'alati farq tufayli new Array ni faqat "n ta bo'sh o'rin" uchun ishlating; tayyor elementli massivni esa [...] bilan yozing.
9. Mashqlar
1-mashq (oson): Hafta kunlari
Array.from bilan [ '1-kun', '2-kun', ... '7-kun' ] massivini yasang va uni bo'sh joy bilan ulab chiqaring.
Yechim
const kunlar = Array.from({ length: 7 }, (_, i) => `${i + 1}-kun`);
console.log(kunlar.join(" "));
// 1-kun 2-kun 3-kun 4-kun 5-kun 6-kun 7-kunIndeks 0 dan boshlanadi, kunlar esa 1 dan — shuning uchun i + 1.
2-mashq (o'rta): Oshxona uchun porsiyalar
Stollarning buyurtmasi { taom, soni } ko'rinishida. Rustam akaga har porsiya alohida qator bo'lgan tekis ro'yxat kerak: osh 2 ta bo'lsa — ikki marta "osh". Keyin ro'yxatdagi har taom sonini reduce bilan sanang.
Ishora: har buyurtmadan soni uzunlikdagi massiv kerak — Array.from({ length: soni }, () => taom). Uni flatMap ichida qaytaring.
const buyurtmalar = [
{ taom: "osh", soni: 2 },
{ taom: "manti", soni: 1 },
{ taom: "osh", soni: 1 },
];Yechim
const buyurtmalar = [
{ taom: "osh", soni: 2 },
{ taom: "manti", soni: 1 },
{ taom: "osh", soni: 1 },
];
const porsiyalar = buyurtmalar.flatMap((b) =>
Array.from({ length: b.soni }, () => b.taom),
);
console.log(porsiyalar); // [ 'osh', 'osh', 'manti', 'osh' ]
const sanoq = porsiyalar.reduce((natija, taom) => {
natija[taom] = (natija[taom] ?? 0) + 1;
return natija;
}, {});
console.log(sanoq); // { osh: 3, manti: 1 }flatMap callback'i har buyurtmadan soni ta elementli massiv qaytardi va ular bitta ro'yxatga to'kildi. Sanoq — reduce darsidagi qolip. Sanoqni porsiyalarsiz, to'g'ridan-to'g'ri soni ni qo'shib ham olish mumkin edi — lekin oshxona ekrani uchun porsiyalar ro'yxatining o'zi kerak.
3-mashq (qiyin): Zal sxemasi
«Bahor» zalida 3 qator, har qatorda 4 ta stol. zal — 3 ta ichki massivdan iborat massiv, har biri 4 ta "bo'sh" satri bilan. So'ng:
- 2-qatordagi 3-stolni "band" qiling — faqat shu bitta stol band bo'lsin (boshqa qatorlar o'zgarmasin).
- Zaldagi barcha band stollar sonini toping (
flat+filter).
Ishora: tashqi massivni Array.from bilan yasang, ichkisini — fill bilan. Nega ichkisi uchun fill xavfsiz, tashqisi uchun — yo'q?
Yechim
const zal = Array.from(
{ length: 3 },
() => new Array(4).fill("bo'sh"),
);
zal[1][2] = "band";
for (const qator of zal) {
console.log(qator.join(" | "));
}
console.log(zal.flat().filter((s) => s === "band").length); // 1Konsolda:
bo'sh | bo'sh | bo'sh | bo'sh
bo'sh | bo'sh | band | bo'sh
bo'sh | bo'sh | bo'sh | bo'sh
1Ichki massivlar satrlar bilan to'ldirildi — satr nusxalanadi, fill xavfsiz. Tashqi massivga esa massivlar kerak: new Array(3).fill(new Array(4).fill("bo'sh")) deb yozilganida uchala qator bitta massiv bo'lardi va "band" har qatorda chiqardi. Array.from callback'i har qator uchun yangi ichki massiv yasadi. 2-qator — indeks 1, 3-stol — indeks 2.
4-mashq: Vazifalar qadami — yuzlab sinov vazifasi
vazifalar da hozir uchta vazifa. Ilova 500 ta vazifada qanday ishlaydi? Bajarilmaganlar tepada turadimi, hisob to'g'rimi, sahifa sekinlashmaydimi? Buni qo'lda 500 marta "Qo'shish" bosib tekshirib bo'lmaydi. Sinov ma'lumotini Array.from bilan yasaymiz.
Bu qadamda vazifalar.js o'zgarmaydi. vazifalar.js oddiy <script> sifatida ulangan, shuning uchun uning yuqori darajadagi holat va render nomlari DevTools konsolidan ko'rinadi. Ishimiz shu konsolda bo'ladi.
vazifalarni brauzerda oching, DevTools → Console.- 500 ta vazifa yasang:
id— 1 dan 500 gacha,matn—Sinov vazifasi 1…, har uchinchisi (i % 3 === 0) bajarilgan.holat.keyingiIdni ham to'g'rilang. render()ni chaqiring va vaqtiniperformance.nowbilan o'lchang.- Konsolga yozgan kod parchangizni — dasturchilar uni snippet deyishadi — keyingi safar uchun
kurs/mashqlar/10/07-sinov/sinov-vazifalar.jsga saqlang.
Yechim
Konsolga:
holat.vazifalar = Array.from({ length: 500 }, (_, i) => ({
id: i + 1,
matn: `Sinov vazifasi ${i + 1}`,
bajarildi: i % 3 === 0,
}));
holat.keyingiId = 501;
const boshi = performance.now();
render();
console.log(`render: ${(performance.now() - boshi).toFixed(1)} ms`);
console.log(`${royxat.children.length} qator, ${hisob.textContent}`);Biz Chrome 154 da ko'rgan natija (vaqt har safar va har kompyuterda biroz farq qiladi — bizda 5–8 ms):
render: 5.2 ms
500 qator, 333 ta vazifa qoldiNimani tekshirdik:
- 500 qator chizildi, hisob — "333 ta vazifa qoldi".
i % 3 === 0— 0, 3, 6, … 498: 167 ta bajarilgan, 500 − 167 = 333 faol. Hisob to'g'ri. - Tartib. Ro'yxat boshida — 2, 3, 5, 6 … (faollar), oxirida — 1, 4, 7 … 499 (bajarilganlar).
sortdarsidagi barqaror saralash yuzlab elementda ham guruh ichidagi tartibni saqladi. - Tezlik. 500 qator bir necha millisekundda chizildi — ko'z sezmaydi. Butun ro'yxatni qayta chizish bu hajmda muammo emas.
- Xulq. "1" ni qaytaring — u faollar boshiga chiqadi, hisob 334 ga oshadi. Filtrlar, tahrirlash va o'chirish ham ishlaydi.
Sahifani yangilang — hammasi boshlang'ich uch vazifaga qaytadi: saqlash yo'q (u 11-qismda). Sinov ma'lumoti faqat konsolda yashadi va loyihaning o'ziga tegmadi.
Kod parchasini kurs/mashqlar/10/07-sinov/sinov-vazifalar.js ga saqlang — u Metod zanjiri darsida o'lchov uchun yana kerak bo'ladi. Faylning boshiga izoh yozing: // DevTools konsoliga ko'chirish uchun — vazifalar.js ga qo'shmang. Bu mashqlar repo'sining fayli:
git add 10/07-sinov
git commit -m "10/07: vazifalar uchun sinov ma'lumoti (Array.from)"vazifalar repo'sida esa bu safar commit yo'q — kod o'zgarmadi.
10. Real ishda
- API javoblari. Serverdan kelgan "buyurtmalar → mahsulotlar" kabi ichma-ich ma'lumotni bitta ro'yxatga yig'ish —
flatMap. Masalan, barcha buyurtmalardagi mahsulotlarni ombor hisobotiga chiqarish. - Sinov ma'lumoti. Test va dizayn uchun yuzlab soxta yozuv yasash —
Array.from({ length: n }, ...). Bugungi 4-mashq — real jamoalardagi kundalik ish. - Kalendar va jadvallar. Oy kunlari, soatlik katakchalar, o'rindiqlar sxemasi — diapazon va ikki o'lchamli massiv. Kinoteatr yoki avtobus o'rindiqlarini band qilish sahifasi aynan 3-mashqdagi
zal. - DOM bilan ishlash.
Array.from(document.querySelectorAll(...))—NodeListni to'liq massivga aylantirishning standart usuli. - Intervyu. "Massivni qanday tekislaysiz?", "
new Array(3).fill([])dagi xato nima?", "1 dan n gacha massivni qanday yasaysiz?" — uchala savolga ham bugun javob oldingiz.
Xulosa
flat(chuqurlik)ichma-ich massivni tekislaydi; sukut bo'yicha bir qavat,Infinity— hammasi. Teshiklarni tashlaydi.flatMap(f)—map(f).flat(): callback[]qaytarsa element yo'qoladi,[x, y]— ikkitaga ko'payadi. Faqat bir qavat.fillasl massivni o'zgartiradi; obyekt bilan to'ldirsa — hamma o'rinda bitta obyekt.Array.from(x, f)— iterable yoki massivga o'xshash obyektdan massiv;{ length: n }bilan diapazon va jadval yasaladi.new Array(n).map(...)ishlamaydi — teshiklar; o'rnigaArray.from({ length: n }, ...).
Keyingi dars: Guruhlash: Object.groupBy va Map.groupBy — ro'yxatni bitta chaqiruv bilan guruhlarga ajratish va vazifalar statistikasini yig'ish.
Manbalar
- MDN: "Array.prototype.flat()", "flatMap()", "fill()", "copyWithin()", "Array.from()" — developer.mozilla.org
- web-features: "Array flat() and flatMap()" — Baseline 2020; "Array.from()" — Baseline 2016
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!