Mundarija (38)
- Bu darsda
- 1. Nega bu kerak?
- 2. Birinchi filter
- 2.1 Arzon narxlar
- 2.2 filter ning va'dalari
- 2.3 filter ichidan
- 3. Predikat — "ha yoki yo'q" funksiya
- 3.1 Atama
- 3.2 Predikatga qanday nom berish kerak
- 3.3 Bir nechta shart
- 3.4 Teskari shart
- 4. Truthy va falsy: filter(Boolean)
- 4.1 filter faqat true ni kutmaydi
- 4.2 Tuzoq: 0 ham falsy
- 5. Obyektlar bilan filter
- 5.1 Elementlar nusxalanmaydi
- 5.2 Elementni xavfsiz o'chirish
- 5.3 Indeks bilan: takrorlarni olib tashlash
- 6. Zanjir: filter + map
- 6.1 Ketma-ket ulash
- 6.2 Tartib muhim
- 6.3 Obyektni filtrlash
- 7. filter, find va some farqi
- 8. Brauzerda: jonli qidiruv
- 9. Ko'p uchraydigan xatolar
- 9.1 Jingalak qavsli predikatda return yo'q
- 9.2 Bo'sh massiv — truthy
- 9.3 Bitta element uchun filter(...)[0]
- 9.4 Predikat ichida ma'lumotni o'zgartirish
- 9.5 Natijani saqlamaslik
- 10. Mashqlar
- 1-mashq (oson): O'tgan talabalar
- 2-mashq (o'rta): Yetkazilmagan buyurtmalar
- 3-mashq (qiyin): Qidiruv funksiyasi
- 4-mashq: Vazifalar qadami — korinadiganlar bitta qatorda
- 11. Real ishda
- Xulosa
- Manbalar
JavaScript filter metodi: massivdan shart bo'yicha tanlash
Qisqacha:
filtermassivning har elementi uchun callback'ni chaqiradi va callback truthy qiymat qaytargan elementlardan yangi massiv yasaydi:narxlar.filter((n) => n <= 30000). Asl massiv o'zgarmaydi, natija esa bo'sh bo'lishi ham mumkin —[]. "Ro'yxatdan faqat kerakligini qoldir" degan har vazifa —filterning ishi.
Bu darsda
filterbilan sonlar, satrlar va obyektlar massividan kerakli elementlarni tanlay olasiz.- Predikat funksiya nima ekanini va unga qanday nom berishni bilasiz.
filter(Boolean)ning ishini va uning tuzog'ini tushuntira olasiz.filtervamapni zanjir qilib ulay olasiz vafilter,find,somefarqini aytib bera olasiz.vazifalardagikorinadiganlarni bitta qatorga tushirasiz — 09-qismdagi va'da bajariladi.
Oldin bilishingiz kerak: Callback imzosi va HOF metodlari, map: har elementni o'zgartirish, Boolean va truthy/falsy qiymatlar, Massivda qidirish va tekshirish, Holatdan UI chizish.
1. Nega bu kerak?
09-qismning ikki darsida bir xil kodni yozgan edik. Holatdan UI chizish darsida — korinadiganIshlar, Yakuniy loyiha darsida — korinadiganlar:
function korinadiganlar() {
const natija = [];
for (const vazifa of holat.vazifalar) {
if (mosmi(vazifa, holat.filtr)) {
natija.push(vazifa);
}
}
return natija;
}Ikkala darsda ham "massivning maxsus filter metodi bor, uni 10-qismda o'rganamiz" degan edik. 09-qism yakunida esa aniqroq va'da berdik: shu funksiyani bitta qatorda yozasiz. Bugun shu va'dani bajaramiz.
Massiv bo'ylab yurish darsida yana bir muammo bor edi. Savatdan hamma "sut" ni splice bilan o'chirmoqchi bo'ldik va bittasi qolib ketdi. O'sha darsda "keyinroq filter bu vazifani massivga tegmasdan, xavfsiz bajaradi" degan edik.
Hayotdan o'xshatish: un elagi. Uyda non yopishdan oldin unni elakdan o'tkazasiz. Mayin un idishga tushadi, kepak va qum elakda qoladi. Elak hech narsani o'zgartirmaydi — faqat tanlaydi. filter ham shunday: elementlar o'zgarmaydi, faqat shartdan o'tganlari yangi massivga tushadi. Inglizcha "filter" so'zining o'zi ham "elak, suzgich" degani.
Reja shunday. Avval filter ni sonlarda ko'ramiz va uning ichini o'zimiz yozib chiqamiz. Keyin callback'ning maxsus nomini — predikatni — o'rganamiz. So'ng truthy/falsy tuzog'i, obyektlar va map bilan zanjir keladi. Oxirida brauzerda jonli qidiruv yasaymiz va vazifalar ga qaytamiz.
Har qadamda bitta savolni yodda tuting: "men tanlayapmanmi yoki aylantiryapmanmi?" Tanlash — filter, aylantirish — map.
2. Birinchi filter
2.1 Arzon narxlar
Talaba mehmon «Bahor»dan 30 000 so'mgacha bo'lgan taomlarni so'radi:
const narxlar = [35000, 28000, 30000, 5000];
const arzonlar = narxlar.filter((narx) => narx <= 30000);
console.log(arzonlar); // [ 28000, 30000, 5000 ]
console.log(narxlar); // [ 35000, 28000, 30000, 5000 ]Callback (narx) => narx <= 30000 har element uchun savolga javob beradi: "seni olaymi?" true qaytsa — element yangi massivga tushadi. false — tushmaydi. Tartib saqlanadi, asl massiv o'zgarmaydi.
Qadamma-qadam ko'ring. Keyingi tugmasini bosib, qaysi element o'tib, qaysi biri qolishini kuzating:
2.2 filter ning va'dalari
| Va'da | Ma'nosi |
|---|---|
| Yangi massiv | Natija — boshqa massiv, asl massiv o'zgarmaydi |
| Uzunlik ≤ asl | Hech bir element mos kelmasa — bo'sh massiv [] |
| Tartib saqlanadi | O'tgan elementlar asl tartibida turadi |
| Elementlar o'sha-o'sha | Elementlar nusxalanmaydi, o'zgarmaydi |
map bilan solishtiring. map — uzunlik bir xil, elementlar aylanadi. filter — uzunlik kamayishi mumkin, elementlar o'zgarmaydi. Bittasi "aylantiradi", ikkinchisi "tanlaydi". Ikkalasini bitta metodda qilish kerak bo'lsa — ularni ketma-ket ulaymiz, buni «Zanjir» bo'limida ko'ramiz.
2.3 filter ichidan
filter "sehr" emas. Callback imzosi darsida forEach ning nusxasini yozgan edik. filter ning soddalashtirilgan nusxasi ham bir necha qator — va u 09-qismdagi korinadiganlar ga juda o'xshaydi:
function tanla(massiv, predikat) {
const natija = [];
for (let i = 0; i < massiv.length; i++) {
if (predikat(massiv[i], i, massiv)) {
natija.push(massiv[i]);
}
}
return natija;
}
const narxlar = [35000, 28000, 30000, 5000];
const arzonlar = tanla(narxlar, (n) => n <= 30000);
console.log(arzonlar); // [ 28000, 30000, 5000 ]Farqi bitta: korinadiganlar da shart (mosmi(...)) ichkariga qotirib yozilgan edi. tanla da esa shart tashqaridan — callback bo'lib keladi. Shuning uchun bitta tanla istalgan massivni istalgan shart bilan elay oladi. filter — xuddi shu tanla, faqat har massivga tayyor holda biriktirilgan.
E'tibor bering: if ichida callback natijasi true bilan solishtirilmayapti — if uning o'zini tekshiradi. Shuning uchun filter truthy va falsy qiymatlar bilan ishlaydi. Bu «Truthy va falsy» bo'limida muhim bo'ladi.
O'zingiz to'ldiring. [3, 8, 1, 9].filter((x) => x > 5) natijasi — [8, ]. [3, 1].filter((x) => x > 5) natijasi — ].
Tekshirib ko'ring:
["osh", "manti", "choy"].filter((t) => t.length > 3)nima qaytaradi?
Javob
[ 'manti', 'choy' ]. "osh" — 3 harf, 3 > 3 — false, u o'tmadi. "manti" (5) va "choy" (4) o'tdi. Elementlar o'zgarmadi — faqat ulardan biri tushib qoldi.
3. Predikat — "ha yoki yo'q" funksiya
3.1 Atama
filter ga beriladigan callback'ning maxsus nomi bor. Predikat (predicate) — true yoki false qaytaradigan, ya'ni "ha/yo'q" savoliga javob beradigan funksiya. O'xshatish: to'y zali eshigidagi tekshiruvchi. U har mehmonga bitta savol beradi: "taklifnomangiz bormi?" Javob ha bo'lsa — kiradi, yo'q bo'lsa — yo'q. Tekshiruvchi mehmonni o'zgartirmaydi, faqat qaror qabul qiladi.
Siz predikatlarni allaqachon yozgansiz. find, some va every ham predikat oladi (Massivda qidirish). 09-qismdagi mosmi(vazifa, filtr) ham predikat — "bu vazifa filtrga mosmi?".
3.2 Predikatga qanday nom berish kerak
Predikat savolga javob beradi, shuning uchun nomi ham savol shaklida bo'lgani yaxshi. O'zbek tilida buning tayyor vositasi bor — "-mi" qo'shimchasi: arzonmi, faolmi, mosmi, bajarilganmi.
const menyu = [
{ nom: "Osh", narx: 35000, issiq: true },
{ nom: "Lag'mon", narx: 28000, issiq: true },
{ nom: "Manti", narx: 30000, issiq: true },
{ nom: "Ko'k choy", narx: 5000, issiq: false },
];
const arzonmi = (taom) => taom.narx <= 30000;
const issiqmi = (taom) => taom.issiq;
const arzonlar = menyu.filter(arzonmi);
const issiqlar = menyu.filter(issiqmi);
const nomlar = arzonlar.map((t) => t.nom);
console.log(nomlar); // [ "Lag'mon", 'Manti', "Ko'k choy" ]
console.log(issiqlar.length); // 3menyu.filter(arzonmi) — "menyudan arzonlarini tanla" deb o'qiladi. Natijani o'qish uchun map bilan nomlarni oldik — bu ham o'tgan darsdagi usul.
Predikatlarni qavssiz, to'g'ridan-to'g'ri berdik. Bu xavfsiz, chunki ular bitta parametr oladi. Ikki parametrli mosmi(vazifa, filtr) ni esa bunday berib bo'lmaydi — buni «Vazifalar qadami» da ko'ramiz.
3.3 Bir nechta shart
Shartlarni mantiqiy operatorlar bilan birlashtiring:
const menyu = [
{ nom: "Osh", narx: 35000, issiq: true },
{ nom: "Lag'mon", narx: 28000, issiq: true },
{ nom: "Ko'k choy", narx: 5000, issiq: false },
];
const arzonIssiq = menyu.filter((t) => t.issiq && t.narx <= 30000);
console.log(arzonIssiq.map((t) => t.nom)); // [ "Lag'mon" ]&& — ikkala shart ham bajarilsin. || — kamida bittasi. Shart uzun bo'lib ketsa, alohida nomli predikat qiling — o'qilishi osonlashadi.
3.4 Teskari shart
Nomli predikatning yana bir foydasi — uni teskarisiga aylantirish oson. Arzonlar bor, endi qimmatlar kerak. Yangi predikat yozish shart emas:
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Ko'k choy", narx: 5000 },
];
const arzonmi = (taom) => taom.narx <= 30000;
const qimmatlar = menyu.filter((taom) => !arzonmi(taom));
console.log(qimmatlar.map((t) => t.nom)); // [ 'Osh' ]! — mantiqiy "emas". Arrow funksiya predikatni chaqiradi va javobini teskarisiga o'giradi. Shart bitta joyda — arzonmi ichida — yashaydi. Ertaga "arzon" chegarasi 25 000 bo'lsa, faqat shu yerni o'zgartirasiz va ikkala ro'yxat ham to'g'ri bo'ladi.
4. Truthy va falsy: filter(Boolean)
4.1 filter faqat true ni kutmaydi
filter callback qaytargan qiymatni true bilan solishtirmaydi. U qiymat truthymi yoki falsymi — shunga qaraydi (Boolean va truthy/falsy). Falsy qiymatlar: false, 0, "", null, undefined, NaN. Qolgan hammasi — truthy.
Shunga asoslangan mashhur yozuv bor:
const kiritilgan = ["Ali", "", "Malika", null, "Jasur", undefined];
const ismlar = kiritilgan.filter(Boolean);
console.log(ismlar); // [ 'Ali', 'Malika', 'Jasur' ]Boolean — tayyor funksiya: u qiymatni mantiqiy qiymatga aylantiradi (Turlarni aniq o'zgartirish). filter uni predikat sifatida chaqiradi. Bo'sh satr, null va undefined falsy — ular tushib qoladi. Formadan kelgan bo'sh maydonlarni tozalashning eng qisqa yo'li shu.
4.2 Tuzoq: 0 ham falsy
const narxlar = [5000, 0, 28000];
console.log(narxlar.filter(Boolean)); // [ 5000, 28000 ]0 ham tushib qoldi! Agar u "bepul ko'k choy" aksiyasi bo'lsa — mijoz uni menyuda ko'rmaydi. filter(Boolean) "bo'sh narsalarni olib tashla" emas, "falsy narsalarni olib tashla" degani. Sonlar bilan aniq shart yozing:
const narxlar = [5000, 0, 28000, null];
const borlar = narxlar.filter((n) => n !== null);
console.log(borlar); // [ 5000, 0, 28000 ]Tekshirib ko'ring:
[0, 1, "", "0", false].filter(Boolean)nima qaytaradi?
Javob
[ 1, '0' ]. 0, "" va false — falsy. "0" esa bo'sh bo'lmagan satr — truthy, garchi ichida nol bo'lsa ham (Boolean va truthy/falsy darsidagi tuzoq).
5. Obyektlar bilan filter
5.1 Elementlar nusxalanmaydi
filter yangi massiv yasaydi, lekin ichiga o'sha obyektlarni qo'yadi:
const vazifalar = [
{ id: 1, matn: "Non olish", bajarildi: false },
{ id: 2, matn: "DOM darsini takrorlash", bajarildi: true },
];
const faollar = vazifalar.filter((v) => !v.bajarildi);
console.log(faollar[0] === vazifalar[0]); // true
faollar[0].matn = "Non va sut olish";
console.log(vazifalar[0].matn); // Non va sut olishfaollar[0] va vazifalar[0] — bitta obyekt (Havola semantikasi). Filtrlangan massiv orqali o'zgartirsangiz, asl ma'lumot ham o'zgaradi. Bu ko'pincha kerak ham: 09-qismdagi vazifaniAlmashtir aynan shu obyektni o'zgartiradi. Faqat bilib turing: filter — "nusxa" emas, "tanlov".
5.2 Elementni xavfsiz o'chirish
Massiv bo'ylab yurish darsidagi "sut" muammosini eslang: aylanayotganda splice qilsak, element qolib ketadi. filter bilan masala boshqacha qo'yiladi. "Sutlarni o'chir" emas, "sut bo'lmaganlarini qoldir":
const savat = ["sut", "sut", "non", "sut"];
const sutsiz = savat.filter((m) => m !== "sut");
console.log(sutsiz); // [ 'non' ]
console.log(savat.length); // 4Hech narsa qolib ketmadi, chunki filter aylanayotgan massivni o'zgartirmaydi — u yangisini yig'adi. Asl savat butun.
Xuddi shu usul bilan vazifani id bo'yicha o'chirish mumkin. Bu — map darsidagi immutable yangilashning bir turi: asl massivga tegmay, keraksiz elementsiz yangi massiv yasaymiz:
const vazifalar = [
{ id: 1, matn: "Non olish" },
{ id: 2, matn: "DOM darsini takrorlash" },
{ id: 3, matn: "Onamga qo'ng'iroq qilish" },
];
const qolganlar = vazifalar.filter((v) => v.id !== 2);
console.log(qolganlar.map((v) => v.id)); // [ 1, 3 ]Tekshirib ko'ring: Bitta mahsulotni (masalan birinchi "sut" ni) o'chirish kerak bo'lsa,
savat.filter((m) => m !== "sut")to'g'ri keladimi?
Javob
Yo'q — u hamma sutni olib tashlaydi. filter "shu shartga mos hamma elementni" deb o'ylaydi. Bitta aniq elementni o'chirish uchun uni noyob belgi bo'yicha tanlang — id yoki indeks: savat.filter((_, i) => i !== 0). Shuning uchun vazifalarda matn emas, id bor.
09-qismdagi vazifaniOchir findIndex va splice bilan aslini o'zgartiradi — bu ham to'g'ri yo'l, holat ni ataylab o'zgartiradigan funksiyada. filter esa yangi massiv kerak bo'lganda — masalan React'da (17-qism) — asosiy usul.
5.3 Indeks bilan: takrorlarni olib tashlash
Callback imzosi darsidagi uchinchi parametr bu yerda chiroyli ishga tushadi. Buyurtmalar ro'yxatidan har taomni bir martadan qoldiramiz:
const buyurtmalar = ["osh", "choy", "osh", "manti", "choy"];
const taomlar = buyurtmalar.filter(
(taom, i, hammasi) => hammasi.indexOf(taom) === i,
);
console.log(taomlar); // [ 'osh', 'choy', 'manti' ]indexOf qiymatning birinchi uchragan joyini qaytaradi (Massivda qidirish). Har qadamni jadvalda ko'ring:
i |
taom |
indexOf(taom) |
O'tadimi? |
|---|---|---|---|
| 0 | osh | 0 | ha — 0 === 0 |
| 1 | choy | 1 | ha — 1 === 1 |
| 2 | osh | 0 | yo'q — 0 === 2 emas |
| 3 | manti | 3 | ha |
| 4 | choy | 1 | yo'q — 1 === 4 emas |
Ikkinchi "osh" 2-indeksda, lekin indexOf("osh") uni emas, 0-indeksdagi birinchisini topadi. Indekslar mos kelmaydi — u tushib qoladi. Har qiymatning faqat birinchi nusxasi o'tadi. Bu ishni yanada qisqa qiladigan Set ham bor — Set darsida.
6. Zanjir: filter + map
6.1 Ketma-ket ulash
filter massiv qaytaradi. Massivda esa map bor. Demak ularni nuqta bilan ketma-ket yozish mumkin. Oshxona ekraniga faqat faol vazifalarning matnlari kerak:
const vazifalar = [
{ id: 1, matn: "Non olish", bajarildi: false },
{ id: 2, matn: "DOM darsini takrorlash", bajarildi: true },
{ id: 3, matn: "Onamga qo'ng'iroq qilish", bajarildi: false },
];
const matnlar = vazifalar
.filter((v) => !v.bajarildi)
.map((v) => v.matn);
console.log(matnlar); // [ 'Non olish', "Onamga qo'ng'iroq qilish" ]Har metod oldingisining natijasini oladi. Sxemadagi strelkalarga qarang — har bosqichda massiv qanday o'zgaradi:
flowchart LR
A["vazifalar: 3 ta obyekt"] -- "filter: faolmi?" --> B["2 ta obyekt"]
B -- "map: matnini ol" --> C["2 ta satr"]Zanjirni har metod alohida qatorda, nuqta bilan boshlab yozish odat — o'qish oson va telefonda ham sig'adi.
6.2 Tartib muhim
Nega avval filter, keyin map? Ikki sabab bor. Birinchisi: map dan keyin bajarildi maydoni yo'qoladi — satrlarda uni tekshirib bo'lmaydi. Ikkinchisi: avval tanlasak, map kamroq elementni aylantiradi. Ming vazifadan o'ntasi faol bo'lsa, map ming marta emas, o'n marta ishlaydi. Qoida sifatida eslab qoling: avval keraksizini olib tashlang, keyin qolganini ishlang.
Zanjirlar haqida batafsil — o'qiluvchanlik, tezlik va qachon oddiy sikl yaxshiroq — Metod zanjiri darsida.
6.3 Obyektni filtrlash
Obyekt bo'ylab yurish darsida arzon taomlarni sikl bilan tanlagan edik va "filter bilan bu bitta qatorga tushadi" degan edik:
const menyu = { osh: 35000, lagmon: 28000, choy: 5000, non: 4000 };
const arzonMenyu = Object.fromEntries(
Object.entries(menyu).filter(([, narx]) => narx <= 10000),
);
console.log(arzonMenyu); // { choy: 5000, non: 4000 }([, narx]) — juftlikning birinchi qismini (nomni) o'tkazib, faqat narxni olamiz (Massiv destructuring). Non narxi — misol uchun.
Tekshirib ko'ring:
[5, 12, 8, 20].filter((x) => x > 6).map((x) => x * 10)nima qaytaradi?
Javob
[ 120, 80, 200 ]. Avval filter: [12, 8, 20] (5 o'tmadi). Keyin map har birini 10 ga ko'paytirdi. Uchta element kirdi — uchta chiqdi.
7. filter, find va some farqi
Uchalasi ham predikat oladi. Farq — nima qaytarishida va qachon to'xtashida:
| Metod | Qaytaradi | Hech biri mos kelmasa | To'xtaydimi? |
|---|---|---|---|
filter |
mos hammasi — massiv | [] |
yo'q, oxirigacha |
find |
birinchi mos element | undefined |
ha, topishi bilan |
some |
true / false |
false |
ha, topishi bilan |
Qaysi birini tanlash — savolga bog'liq. "Arzon taomlar qaysilar?" — filter. "Birinchi arzon taom qaysi?" — find. "Arzon taom bormi?" — some. Massivda qidirish darsida "find va filter farqi" intervyu savoli ekanini aytgan edik — mana javob.
filter ni find yoki some o'rnida ishlatish — ko'p uchraydigan xato. Buni «Ko'p uchraydigan xatolar» bo'limida ko'ramiz.
Farqni bitta tajribada ko'ring. Callback ichiga kuzatish uchun console.log qo'yamiz va uchala metodga bir xil savol beramiz — "30 000 dan arzonmi?":
const narxlar = [35000, 28000, 5000];
let chaqiruv = 0;
const arzonmi = (n) => {
chaqiruv++;
return n < 30000;
};
console.log(narxlar.filter(arzonmi), chaqiruv); // [ 28000, 5000 ] 3
chaqiruv = 0;
console.log(narxlar.find(arzonmi), chaqiruv); // 28000 2
chaqiruv = 0;
console.log(narxlar.some(arzonmi), chaqiruv); // true 2filter callback'ni uch marta chaqirdi — u har elementni ko'rishi shart, chunki "hammasi" kerak. find va some ikkinchi elementda javob topib, to'xtadi. Ming elementli ro'yxatda birinchisi mos kelsa, farq 1 ga qarshi 1000 bo'ladi.
Tekshirib ko'ring: Telegram bot foydalanuvchi yozgan buyruq ro'yxatda borligini tekshirishi kerak.
filter,findyokisome— qaysi biri?
Javob
some — savol "bormi?", javob true/false. U topishi bilan to'xtaydi. filter ham ishlaydi (.length > 0), lekin har buyruqni behuda tekshiradi va keraksiz massiv yasaydi.
8. Brauzerda: jonli qidiruv
Mehmon menyudan taom qidiradi. Har harf yozilganda ro'yxat yangilanadi. Bu filter ning eng ko'p uchraydigan brauzer ishi: holat (menyu) o'zgarmaydi, ekranga esa uning filtrlangan qismi chiziladi (Holatdan UI chizish). Hodisa — input (input va change):
<style>
body { margin: 1rem; font: 1rem/1.5 system-ui, sans-serif; }
input {
font: inherit;
min-height: 2.75rem;
padding: 0.5rem;
border: 2px solid #5b6660;
border-radius: 0.5rem;
}
ul { padding-left: 1.25rem; }
</style>
<label for="qidiruv">Taom qidirish</label>
<input id="qidiruv" type="search" autocomplete="off">
<p id="soni" aria-live="polite"></p>
<ul id="menyu"></ul>
<script>
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Lag'mon", narx: 28000 },
{ nom: "Manti", narx: 30000 },
{ nom: "Ko'k choy", narx: 5000 },
];
const maydon = document.getElementById("qidiruv");
const royxat = document.getElementById("menyu");
const soni = document.getElementById("soni");
function mosmi(taom, soz) {
return taom.nom.toLowerCase().includes(soz.toLowerCase());
}
function taomQatori(taom) {
const li = document.createElement("li");
li.textContent = `${taom.nom} — ${taom.narx} so'm`;
return li;
}
function render(soz) {
const topilganlar = menyu.filter((taom) => mosmi(taom, soz));
royxat.replaceChildren(...topilganlar.map(taomQatori));
soni.textContent = `${topilganlar.length} ta taom topildi`;
}
maydon.addEventListener("input", () => {
render(maydon.value.trim());
});
render("");
console.log(soni.textContent);
</script>Konsolda:
4 ta taom topildiSinab ko'ring:
- Maydonga
oyozing — uchta taom qoladi: Osh, Lag'mon, Ko'k choy. Ularning hammasida "o" harfi bor. madeb yozing — faqat Manti.MAdeb yozsangiz ham — natija o'sha: ikkala tomontoLowerCasebilan kichik harfga keltirilgan (Matnni o'zgartirish).palovdeb yozing — ro'yxat bo'sh, "0 ta taom topildi".filterxato bermadi, shunchaki[]qaytardi.- Maydonni tozalang — to'rttala taom qaytadi. Menyu hech qachon o'zgarmagan edi.
Bu kodda muhim bir qaror bor: filter natijasi hech qayerda saqlanmaydi. topilganlar — render ichidagi vaqtinchalik o'zgaruvchi, har harfda qaytadan hisoblanadi. menyu esa doim to'liq turadi. Agar natijani menyu ning o'ziga yozsak (menyu = menyu.filter(...)), "palov" deb yozgan mehmon menyuni butunlay yo'qotardi — maydonni tozalasa ham taomlar qaytmasdi. Filtrlangan ro'yxat — hosila ma'lumot: u har safar holatdan qayta hisoblanadi va alohida saqlanmaydi (Holatdan UI chizish darsidagi qoida).
Son aria-live="polite" hududida — ko'zi ojiz mehmon Malika NVDA bilan har harfdan keyin "2 ta taom topildi" deb eshitadi (Dinamik UI'da qulaylik). Bu yerda ham ikki parametrli mosmi arrow funksiyaga o'ralgan — sababini quyida, «Vazifalar qadami» da ko'rasiz.
9. Ko'p uchraydigan xatolar
9.1 Jingalak qavsli predikatda return yo'q
const narxlar = [35000, 28000, 5000];
const arzonlar = narxlar.filter((narx) => {
narx <= 30000;
});
console.log(arzonlar); // []Bo'sh massiv — xatosiz. Callback har safar undefined qaytardi, u esa falsy. Bitta ham element o'tmadi. Tuzatish: (narx) => narx <= 30000 yoki { return narx <= 30000; }. Bo'sh natijani ko'rsangiz, avval shu return ni tekshiring.
9.2 Bo'sh massiv — truthy
const menyu = [{ nom: "Osh", narx: 35000 }];
const topilgan = menyu.filter((t) => t.nom === "Palov");
if (topilgan) {
console.log("Bor!");
}
console.log(topilgan); // []Konsolda:
Bor!
[]Palov topilmadi, lekin "Bor!" chiqdi. Sabab: filter doim massiv qaytaradi, bo'sh massiv [] esa truthy (Boolean va truthy/falsy). Tuzatish: savol "bormi?" bo'lsa — some ishlating: menyu.some((t) => t.nom === "Palov"). Yoki uzunlikni tekshiring: topilgan.length > 0.
9.3 Bitta element uchun filter(...)[0]
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Manti", narx: 30000 },
];
const osh = menyu.filter((t) => t.nom === "Osh")[0];
console.log(osh.narx); // 35000Ishlaydi, lekin ortiqcha ish qiladi: filter birinchisini topgandan keyin ham oxirigacha yuradi va keraksiz massiv yasaydi. Tuzatish: menyu.find((t) => t.nom === "Osh") — topishi bilan to'xtaydi va obyektning o'zini qaytaradi.
9.4 Predikat ichida ma'lumotni o'zgartirish
const vazifalar = [{ id: 1, bajarildi: false }];
const faollar = vazifalar.filter((v) => {
v.korildi = true;
return !v.bajarildi;
});
console.log(vazifalar[0].korildi); // truePredikat "faqat so'rash" o'rniga asl obyektga yangi maydon yozib qo'ydi. filter chaqirilgani asl ma'lumotni o'zgartirdi — kodni o'qigan odam buni hech kutmaydi. Callback imzosi darsidagi qoida: callback toza bo'lsin. Tuzatish: predikat faqat return qilsin; belgilash kerak bo'lsa — alohida qadamda va ataylab.
9.5 Natijani saqlamaslik
savat.filter((m) => m !== "sut"); deb yozib, savat dan sut o'chishini kutish. filter aslini o'zgartirmaydi — natijani yangi o'zgaruvchiga yozing: const sutsiz = savat.filter(...). Yoki, let bilan e'lon qilingan bo'lsa, qayta tayinlang: savat = savat.filter(...).
10. Mashqlar
1-mashq (oson): O'tgan talabalar
Imtihon ballari berilgan. filter bilan 60 va undan yuqori ballarni tanlang va nechta talaba o'tganini chiqaring.
const ballar = [45, 78, 60, 91, 33, 59];Yechim
const ballar = [45, 78, 60, 91, 33, 59];
const otganlar = ballar.filter((ball) => ball >= 60);
console.log(otganlar); // [ 78, 60, 91 ]
console.log(otganlar.length); // 3>= — 60 ham o'tadi. > yozilsa, 60 ballik talaba nohaq yiqilardi.
2-mashq (o'rta): Yetkazilmagan buyurtmalar
Kuryer Jasurga hali yetkazilmagan buyurtmalarning manzillari kerak. filter va map zanjiri bilan manzillar massivini yasang.
const buyurtmalar = [
{ id: 1, manzil: "Chilonzor 9", yetkazildi: true },
{ id: 2, manzil: "Yunusobod 4", yetkazildi: false },
{ id: 3, manzil: "Sergeli 2", yetkazildi: false },
];Yechim
const buyurtmalar = [
{ id: 1, manzil: "Chilonzor 9", yetkazildi: true },
{ id: 2, manzil: "Yunusobod 4", yetkazildi: false },
{ id: 3, manzil: "Sergeli 2", yetkazildi: false },
];
const manzillar = buyurtmalar
.filter((b) => !b.yetkazildi)
.map((b) => b.manzil);
console.log(manzillar); // [ 'Yunusobod 4', 'Sergeli 2' ]Avval tanladik, keyin aylantirdik. Teskari tartibda yozsangiz, map dan keyin yetkazildi maydoni yo'qoladi va filtrlab bo'lmaydi.
3-mashq (qiyin): Qidiruv funksiyasi
qidir(menyu, soz, eng = Infinity) funksiyasini yozing. U nomida soz bor (katta-kichik harf farqsiz) va narxi eng dan oshmaydigan taomlarning nomlarini qaytarsin. eng berilmasa — narx cheklanmaydi (Default qiymatlar).
Yechim
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Lag'mon", narx: 28000 },
{ nom: "Manti", narx: 30000 },
{ nom: "Ko'k choy", narx: 5000 },
];
function qidir(taomlar, soz, eng = Infinity) {
const kichik = soz.toLowerCase();
return taomlar
.filter((t) => t.nom.toLowerCase().includes(kichik))
.filter((t) => t.narx <= eng)
.map((t) => t.nom);
}
console.log(qidir(menyu, "O")); // [ 'Osh', "Lag'mon", "Ko'k choy" ]
console.log(qidir(menyu, "o", 30000)); // [ "Lag'mon", "Ko'k choy" ]
console.log(qidir(menyu, "palov")); // []soz.toLowerCase() bir marta, sikldan tashqarida hisoblandi — har element uchun qayta hisoblash shart emas. Ikki filter ni bitta && bilan ham yozsa bo'ladi — ikkalasi ham to'g'ri. Alohida yozilgani o'qishda ikki aniq qadamga bo'linadi. Infinity — har qanday sondan katta, shuning uchun narx <= Infinity doim true (Number turi).
4-mashq: Vazifalar qadami — korinadiganlar bitta qatorda
refactor/hof-metodlar branch'ida davom etamiz. 09-qismdagi va'da: korinadiganlar ni filter bilan yozing. Xulq o'zgarmasin.
Ishora: Callback imzosi darsi oxiridagi savolni eslang — nega holat.vazifalar.filter(mosmi) yozib bo'lmaydi?
Yechim
function korinadiganlar() {
return holat.vazifalar.filter(
(vazifa) => mosmi(vazifa, holat.filtr),
);
}8 qator — bitta return ga tushdi (uzun bo'lgani uchun uch qatorga bo'lib yozdik). mosmi ga o'zgarish kerak emas: u allaqachon predikat edi.
.filter(mosmi) nega yaramaydi — Node'da o'zingiz ko'ring. Eski sikl, yangi filter va xato varianti bir xil holat da:
const holat = {
vazifalar: [
{ id: 1, matn: "Non olish", bajarildi: false },
{ id: 2, matn: "DOM darsini takrorlash", bajarildi: true },
{ id: 3, matn: "Onamga qo'ng'iroq qilish", bajarildi: false },
],
filtr: "faol",
};
function mosmi(vazifa, filtr) {
if (filtr === "faol") {
return !vazifa.bajarildi;
}
if (filtr === "bajarilgan") {
return vazifa.bajarildi;
}
return true;
}
function eskisi() {
const natija = [];
for (const vazifa of holat.vazifalar) {
if (mosmi(vazifa, holat.filtr)) {
natija.push(vazifa);
}
}
return natija;
}
const yangisi = () =>
holat.vazifalar.filter((vazifa) => mosmi(vazifa, holat.filtr));
const xatosi = () => holat.vazifalar.filter(mosmi);
const idlar = (royxat) => royxat.map((v) => v.id).join(",");
for (const filtr of ["hammasi", "faol", "bajarilgan"]) {
holat.filtr = filtr;
const ustunlar = [eskisi(), yangisi(), xatosi()].map(idlar);
console.log(filtr, ...ustunlar);
}Konsolda:
hammasi 1,2,3 1,2,3 1,2,3
faol 1,3 1,3 1,2,3
bajarilgan 2 2 1,2,3Eski va yangi ustunlar hamma filtrda bir xil — refaktoring xulqni o'zgartirmadi. Uchinchi ustun esa doim 1,2,3: mosmi ning filtr parametriga indeks (0, 1, 2) tushdi va har vazifa "hammasi" dagidek o'tdi. Xato xabari yo'q — shuning uchun bunday tekshiruv foydali.
Brauzerda tekshiring:
- «Faol» — "Non olish" va "Onamga qo'ng'iroq qilish". «Bajarilgan» — faqat "DOM darsini takrorlash". «Hammasi» — uchalasi.
- «Faol» da vazifani belgilang — u ro'yxatdan chiqadi, fokus qo'shnisiga o'tadi, hisob kamayadi.
- «Faol» da ikkalasini belgilang — "Faol vazifa yo'q.".
filterbo'sh massiv qaytardi,render()uni avvalgidek ko'rsatdi.
09-qismdagi Yakuniy loyiha 2-mashqi (bajarilganlarniTozala) ni bajargan bo'lsangiz, undagi for...of ni ham almashtiring: holat.vazifalar = holat.vazifalar.filter((v) => !v.bajarildi);. O'chirilganlar soni — eski va yangi uzunliklar farqi.
Commit: Filtr: korinadiganlar ni filter bilan yoz.
11. Real ishda
- Qidiruv va filtrlar. Internet do'kondagi "narx: 100 000 gacha", "faqat chegirmadagilar" tugmalari — ichida
filter. Telegram kontaktlari ichida qidirish ham shunday ishlaydi. - Ma'lumotni tozalash. Formadan yoki fayldan kelgan ro'yxatdan bo'sh qatorlarni olib tashlash:
qatorlar.filter((q) => q.trim() !== ""). - Ruxsatlar. Admin panelda foydalanuvchiga faqat ruxsati bor menyu bandlari ko'rsatiladi:
bandlar.filter((b) => ruxsatlar.includes(b.ruxsat)). Lekin xavfsizlik serverda ham tekshiriladi — brauzerdagifilterni foydalanuvchi DevTools'da chetlab o'tishi mumkin. - Hisobotlar. "Bu oy to'langan buyurtmalar", "Toshkentdagi mijozlar" — har hisobot boshida
filterturadi, keyinmapva yig'indi. Yig'indini qanday olish — keyingi darsda. - Intervyu. "
filtervafindfarqi?", "filterasl massivni o'zgartiradimi?", "[0, 1, ''].filter(Boolean)nima beradi?" — endi uchalasiga ham javobingiz bor.
Xulosa
filterpredikat truthy qaytargan elementlardan yangi massiv yasaydi; asl massiv o'zgarmaydi.- Natija qisqaroq yoki bo'sh (
[]) bo'lishi mumkin; elementlar nusxalanmaydi — o'sha obyektlar. - Predikat nomi savol shaklida:
arzonmi,faolmi. Ikki parametrlisini arrow bilan o'rang. filter(Boolean)falsy qiymatlarni, shu jumladan0ni ham olib tashlaydi.- Avval
filter, keyinmap— tanlash, keyin aylantirish. - Hammasi kerak —
filter, birinchisi —find, bormi-yo'qmi —some. - Filtrlangan ro'yxat — hosila: uni har safar holatdan qayta hisoblang, asl massiv o'rniga saqlamang. Elementni xavfsiz o'chirish —
filter((v) => v.id !== id), aylanayotgandaspliceemas.
Keyingi dars: reduce: massivni bitta qiymatga yig'ish — massivdan son, obyekt yoki istalgan natijani akkumulyator bilan yig'amiz va vazifalar dagi oxirgi for...of siklini ham almashtiramiz.
Manbalar
- MDN: "Array.prototype.filter()" — developer.mozilla.org
- MDN: "Truthy", "Falsy" — developer.mozilla.org
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!