IlmHamroh
JavaScript Full-stack/10-qism. JavaScript chuqur45/65-dars18 daqiqa
Mundarija (33)

JavaScript Set: faqat takrorlanmas qiymatlar to'plami

Qisqacha: Set — har qiymatni faqat bir marta saqlaydigan to'plam. Bir xil qiymatni ikkinchi marta qo'shsangiz, u e'tiborsiz qoldiriladi. Massivdagi takrorlarni olib tashlash — bitta qator: [...new Set(massiv)]. "Bu qiymat bormi?" savoliga set.has(x) katta ro'yxatda ham deyarli bir zumda javob beradi.

Bu darsda

  • Set yaratib, add, has, delete, clear va size bilan ishlay olasiz.
  • Massivdan takrorlarni bitta qatorda olib tashlay olasiz va bu qachon ishlamasligini bilasiz.
  • Set bo'ylab yura olasiz va uni massivga aylantira olasiz.
  • Nega has katta ro'yxatda includes dan ming marta tez ekanini o'lchov bilan ko'rasiz.
  • vazifalar dagi teglarni takrorsiz qilasiz.

Oldin bilishingiz kerak: Map, Massivda qidirish va tekshirish, filter, Spread va rest operatori, flat, flatMap, fill va Array.from.

1. Nega bu kerak?

Kurs davomida bitta savol bir necha marta chiqdi: "har qiymat bir marta qolsin".

  • filter darsida takrorlarni indexOf bilan olib tashladik: taomlar.filter((t, i, hammasi) => hammasi.indexOf(t) === i). U ishlaydi, lekin uni o'qib tushunish uchun to'xtab o'ylash kerak.
  • flat darsida stollarning buyurtmalarini birlashtirganda "choy" ikki marta qoldi.
  • 03-qismda, masala yechish darsida, "daftarda bormi?" savoliga tez javob beradigan to'plam haqida aytgan edik.

Uchalasiga javob bitta — Set. Hayotdan o'xshatish: to'y taklifnomalari ro'yxati. Opangiz ham, xolangiz ham "Aziza opani yozib qo'y" deydi. Ro'yxatda Aziza opa baribir bir marta turadi. Ikkinchi marta yozishga urinsangiz — "u bor-ku" deysiz. Kimdir "Aziza opa bormi?" deb so'rasa, butun ro'yxatni boshidan o'qib chiqmaysiz.

2. Set yaratish va asosiy metodlar

2.1 Birinchi Set

To'plam (set) — har qiymat ko'pi bilan bir marta uchraydigan qiymatlar guruhi. JavaScript'da u Set klassi bilan yaratiladi:

js
const taomlar = new Set();

taomlar.add("osh");
taomlar.add("choy");
taomlar.add("osh");

console.log(taomlar.size); // 2
console.log(taomlar);

Konsolda:

text
2
Set(2) { 'osh', 'choy' }

"osh" ikki marta qo'shildi, lekin Set da u bitta. Xato ham, ogohlantirish ham yo'q — ikkinchi add shunchaki hech narsa qilmadi. Node Set ni Set(2) { ... } ko'rinishida chiqaradi: Map dagidan farqi — strelka yo'q, faqat qiymatlar. Brauzer konsoli Set(2) {'osh', 'choy'} ko'rsatadi — ma'nosi bir xil.

2.2 Metodlar

Set ning metodlari Map ga juda o'xshaydi, faqat kalit-qiymat juftligi o'rniga bitta qiymat:

Yozuv Nima qiladi Qaytaradi
s.add(q) qiymat qo'shadi (bor bo'lsa — hech narsa) Set ning o'zi
s.has(q) qiymat bormi? true / false
s.delete(q) qiymatni o'chiradi o'chdimi: true / false
s.clear() hammasini o'chiradi undefined
s.size qiymatlar soni son

get yo'q. Nega? Set dan nima olish mumkin? Faqat siz bergan qiymatning o'zini. Savol faqat bitta: "bormi yoki yo'qmi" — buni has beradi.

Otabek bugun kelgan mehmonlarni belgilab boradi:

js
const kelganlar = new Set();

kelganlar.add("Dilshod aka").add("Malika").add("Bobur");
console.log(kelganlar.has("Malika")); // true
console.log(kelganlar.has("Nodira")); // false

console.log(kelganlar.delete("Bobur")); // true
console.log(kelganlar.delete("Bobur")); // false
console.log(kelganlar.size); // 2

add ham Map dagi set kabi to'plamning o'zini qaytaradi — zanjir qilish mumkin.

2.3 Tayyor qiymatlardan yaratish

new Set() ga massiv bersangiz, Set darhol to'ladi — takrorlar tushib qoladi:

js
const buyurtmalar = ["osh", "manti", "osh", "choy", "manti"];
const turlar = new Set(buyurtmalar);

console.log(turlar); // Set(3) { 'osh', 'manti', 'choy' }

Massiv o'rniga satr bersangiz — natija kutilmagan bo'lishi mumkin:

js
console.log(new Set("salom")); // Set(5) { 's', 'a', 'l', 'o', 'm' }
console.log(new Set(["salom"])); // Set(1) { 'salom' }

new Set unga berilgan narsani elementlarga bo'lib aylanib chiqadi. Satrning elementlari — harflar. Bitta so'zni qo'shmoqchi bo'lsangiz — uni massivga o'rang.

Son esa umuman aylanib chiqib bo'lmaydigan qiymat:

js
const s = new Set(5);
text
TypeError: number 5 is not iterable (cannot read property Symbol(Symbol.iterator))

Tarjimasi: "5 soni — aylanib chiqib bo'lmaydigan (iterable emas) qiymat (Symbol(Symbol.iterator) xususiyatini o'qib bo'lmadi)". Iterable — for...of bilan aylanib chiqish mumkin bo'lgan qiymat: massiv, satr, Map, Set. Qavs ichidagi g'alati nom — Symbol.iterator — JavaScript aynan shuni qidirgan. U nima ekanini Well-known symbols darsida ochamiz. Hozircha qoida: new Set(...) ga massiv, satr yoki boshqa to'plam bering.

Tekshirib ko'ring: new Set(["a", "b", "a", "c", "b"]).size nimaga teng?

Javob

3. Takrorlangan "a" va "b" bir martadan qoladi: { 'a', 'b', 'c' }. size — qolgan qiymatlar soni, massivdagi elementlar soni emas.

3. Takrorlarni olib tashlash

3.1 Bitta qator

Massivdan takrorlarni olib tashlash va yana massiv olish — Set ning eng mashhur ishlatilishi:

js
const buyurtmalar = ["osh", "manti", "osh", "choy", "manti"];

const takrorsiz = [...new Set(buyurtmalar)];
console.log(takrorsiz); // [ 'osh', 'manti', 'choy' ]

Ikki qadam bor. new Set(...) takrorlarni tashlaydi. Spread [...] esa natijani yana massivga yoyadi. Array.from(new Set(buyurtmalar)) ham xuddi shunday ishlaydi (Array.from).

Tartib — har qiymatning birinchi uchragan joyi. "osh" birinchi turgan edi — birinchi qoldi. Bu kafolat: Set ham Map kabi qo'shilish tartibini saqlaydi.

3.2 Ichida nima bo'lyapti

new Set(massiv) aslida har elementga add qiladi. Keyingi tugmasini bosib, takror qiymat qanday "o'tib ketishini" kuzating:

O'zingiz to'ldiring. [...new Set([3, 1, 3, 2, 1])] natijasi — [3, 1, 2]. Uning uzunligi — [:3], birinchi elementi — [:3].

3.3 Eski usul bilan solishtirish

filter darsidagi variant va yangisi bir xil natija beradi:

js
const taomlar = ["osh", "choy", "osh", "manti", "choy"];

const eski = taomlar.filter(
  (t, i, hammasi) => hammasi.indexOf(t) === i,
);
const yangi = [...new Set(taomlar)];

console.log(eski); // [ 'osh', 'choy', 'manti' ]
console.log(yangi); // [ 'osh', 'choy', 'manti' ]

Natija bir xil, lekin ikkinchisi niyatni darhol aytadi: "takrorsiz to'plam". Bundan tashqari eski usul har element uchun indexOf bilan massivni boshidan qidiradi — katta ro'yxatda bu sekin. Qanchalik sekinligini «Tezlik» bo'limida o'lchaymiz.

Bitta farq ham bor. indexOf NaN ni topa olmaydi, shuning uchun eski usul NaN larni butunlay tashlab yuboradi. Set esa bitta NaN ni qoldiradi — keyingi bo'limda sababini ko'ramiz.

4. Qaysi qiymatlar "bir xil"?

4.1 Primitivlar: SameValueZero

Set ham Map kabi qiymatlarni SameValueZero qoidasi bilan solishtiradi (Tenglik operatorlari): deyarli ===, faqat NaN o'ziga teng. 0 va -0 — bitta qiymat. Son va satr — har xil:

js
const s = new Set([1, "1", NaN, NaN, 0, -0]);

console.log(s); // Set(4) { 1, '1', NaN, 0 }

4.2 Obyektlar: havola bo'yicha

Endi eng ko'p qoqiladigan joy. Ikki bir xil ko'rinishli obyekt Set uchun ikki xil qiymat:

js
const bronlar = [
  { ism: "Malika", telefon: "+998 90 000 00 01" },
  { ism: "Malika", telefon: "+998 90 000 00 01" },
];

console.log(new Set(bronlar).size); // 2

Havola semantikasi darsini eslang: har { ... } — xotirada yangi obyekt. Set ichidagi ma'lumotga qaramaydi, faqat "bu aynan o'sha obyektmi?" deb so'raydi.

Obyektlarni biror kalit bo'yicha takrorsiz qilish kerak bo'lsa — kalitni Set ga yig'ib, "ko'rildimi?" deb tekshiramiz:

js
const bronlar = [
  { ism: "Malika", telefon: "+998 90 000 00 01" },
  { ism: "Bobur", telefon: "+998 90 000 00 02" },
  { ism: "Malika", telefon: "+998 90 000 00 01" },
];

const korilgan = new Set();
const takrorsiz = bronlar.filter((b) => {
  if (korilgan.has(b.telefon)) {
    return false;
  }
  korilgan.add(b.telefon);
  return true;
});

console.log(takrorsiz.map((b) => b.ism)); // [ 'Malika', 'Bobur' ]

Diqqat: bu filter callback'i korilgan ni o'zgartiradi. Bu — Callback imzosi darsidagi "callback faqat so'rasin" qoidasidan ongli chekinish. U callback ichida yaratilgan emas, lekin faqat shu bitta amal uchun yashaydi va tashqariga chiqmaydi. Bunday yordamchi Set — ko'p uchraydigan, qabul qilingan qolip.

Tekshirib ko'ring: const a = { id: 1 }; new Set([a, a, { id: 1 }]).size nimaga teng?

Javob

2. Birinchi ikkitasi — bitta obyekt (a havolasi ikki marta), ular bitta qiymat bo'lib qoladi. Uchinchisi — yangi obyekt, ichi bir xil bo'lsa ham alohida.

5. Set bo'ylab yurish

5.1 for...of va massivga aylantirish

Set ni for...of bilan aylanish mumkin — qo'shilgan tartibda:

js
const turlar = new Set(["osh", "manti", "choy"]);

for (const taom of turlar) {
  console.log(taom.toUpperCase());
}

Konsolda:

text
OSH
MANTI
CHOY

Lekin Set massiv emas. Unda indeks yo'q va map, filter, reduce metodlari yo'q:

js
const turlar = new Set(["osh", "manti"]);

console.log(turlar[0]); // undefined
console.log([...turlar].map((t) => t.length)); // [ 3, 5 ]

turlar[0] xato bermadi — Set ham obyekt, unda shunchaki "0" nomli xususiyat yo'q. Massiv metodlari kerak bo'lsa — avval [...turlar].

5.2 forEach va g'alati imzo

Set da ham forEach bor. Uning callback'i ham uchta argument oladi — lekin birinchi ikkitasi bir xil:

js
const turlar = new Set(["osh"]);

turlar.forEach((qiymat, yana, hammasi) => {
  console.log(qiymat, yana, hammasi.size);
});

Konsolda:

text
osh osh 1

Nega? Map da forEach (qiymat, kalit, map) beradi. Set ning kaliti yo'q, lekin imzo bir xil bo'lishi uchun kalit o'rniga yana qiymatning o'zi beriladi. Shu sabab bilan keys() va values() bir xil natija beradi, entries() esa [qiymat, qiymat] juftliklarini:

js
const turlar = new Set(["osh", "choy"]);

console.log([...turlar.keys()]);
console.log([...turlar.values()]);
console.log([...turlar.entries()]);

Konsolda:

text
[ 'osh', 'choy' ]
[ 'osh', 'choy' ]
[ [ 'osh', 'osh' ], [ 'choy', 'choy' ] ]

Bularni bilish — tanib olish uchun. Amalda Set bilan for...of va spread yetarli.

5.3 Aylanish paytida o'zgartirish

Callback imzosi darsida massivni aylanayotganda unga push qilsak, yangi elementlar ko'rilmasligini ko'rgan edik: forEach uzunlikni boshida eslab qoladi. Set da xulq boshqacha — aylanish paytida qo'shilgan qiymat ham ko'riladi:

js
const navbat = new Set(["Ali"]);

for (const ism of navbat) {
  console.log(ism);
  if (ism === "Ali") {
    navbat.add("Vali");
  }
}

Konsolda:

text
Ali
Vali

"Vali" sikl boshlanganda yo'q edi, lekin u ham chiqdi. for...of Set ni "jonli" aylanadi: har qadamda "keyingi qiymat bormi?" deb so'raydi. Ehtiyot bo'ling: har qadamda yangi qiymat qo'shsangiz, sikl hech qachon tugamaydi. Joriy qiymatni o'chirish esa xavfsiz — keyingilari baribir ko'riladi. Map ham xuddi shunday ishlaydi.

Qoida massivdagidek: aylanayotgan to'plamni o'zgartirishdan qoching. Kerak bo'lsa — avval nusxa oling ([...navbat]) va nusxani aylaning.

5.4 JSON

Map kabi Set ham JSON'ga to'g'ridan-to'g'ri yozilmaydi (JSON chuqur):

js
const turlar = new Set(["osh", "choy"]);

console.log(JSON.stringify(turlar)); // {}
console.log(JSON.stringify([...turlar])); // ["osh","choy"]

Saqlashdan oldin massivga aylantiring, o'qigach — new Set(JSON.parse(matn)).

6. Tezlik: has va includes

Massivda "bormi?" deb so'rash uchun includes bor. U massivni boshidan bittalab ko'rib chiqadi — 100 000 elementli ro'yxatda, eng yomon holatda, 100 000 ta taqqoslash. Set esa qiymatlarni maxsus tuzilmada saqlaydi. Uning nomi — xesh jadval (hash table): har qiymatdan "manzil raqami" hisoblanadi va qiymat shu raqamli katakka qo'yiladi. "Bormi?" deb so'raganda Set raqamni yana hisoblaydi va to'g'ri o'sha katakka qaraydi — ro'yxat qanchalik katta bo'lmasin.

Hayotdan o'xshatish: kiyim saqlash xonasidagi raqamli ilgaklar. 57-jeton bilan kelsangiz, xodim hamma paltoni ko'zdan kechirmaydi — to'g'ri 57-ilgakka boradi. includes esa raqamsiz xona: paltongizni topish uchun hammasini birma-bir ko'rish kerak.

O'lchab ko'ramiz. Telefon raqamlari ro'yxatida 10 000 ta raqamni qidiramiz: avval massivda includes bilan, keyin Set da has bilan.

js
const raqamlar = Array.from(
  { length: N },
  (_, i) => "+99890" + String(i).padStart(7, "0"),
);
const toplam = new Set(raqamlar);
// 10 000 marta: raqamlar.includes(q)  va  toplam.has(q)

Natijaga qarang: chiziqlardan biri tepaga uchib ketadi, ikkinchisi esa pastda deyarli yotib qoladi.

10 000 ta qidiruv vaqti
Vaqt, ms
10 3000,61 000100 000Ro'yxatdagi raqamlar, tamassiv.includes: 1 000 ta → 110 msmassiv.includes: 10 000 ta → 1 100 msmassiv.includes: 100 000 ta → 10 300 msset.has: 1 000 ta → 1 msset.has: 10 000 ta → 0,6 msset.has: 100 000 ta → 1 ms
  • massiv.includes
  • set.has
10 000 ta qidiruv vaqti
Ro'yxatdagi raqamlarmassiv.includesset.has
1 000110
10 0001 100
100 00010 300
1 0001
10 0000,6
100 0001

Manba: O'lchov: Node 24.21, Windows 11 noutbuk, 2026-10-04; 3 marta takrorlab o'rtachasi olindi

Ro'yxat 10 marta o'sganda includes ham taxminan 10 marta sekinlashdi: 110 → 1 100 → 10 300 ms. has esa har uch holatda bir millisekund atrofida qoldi. 100 000 raqamda farq — o'n ming marta.

Raqamlar kompyuterga qarab o'zgaradi, lekin shakl o'zgarmaydi. Bunday o'sishni "O(n)" va "O(1)" deb belgilashadi — buni Big-O darsida o'rganamiz, hozir bilish shart emas.

Amaliy qoida:

  • Bir-ikki marta, kichik ro'yxatda tekshirish — includes yetarli.
  • Ko'p marta yoki katta ro'yxatda tekshirish (siklda, har harf terilganda) — avval bir marta Set yasang, keyin has.

Lekin Set ni yasashning o'zi ham vaqt oladi: u har elementni bir marta ko'rib chiqadi. Bitta tekshiruv uchun massivdan Set yasash — bir marta includes qilishdan sekinroq. Foyda faqat bir marta yasab, ko'p marta so'raganda keladi.

Massiv qachon hamon yaxshiroq? Tartib va indeks muhim bo'lganda: navbat, reyting. Takror qiymatlar kerak bo'lganda: savatda ikkita osh. Qisqasi, Set "nima bor?" degan savolga javob beradi. Massiv esa "nima, qaysi tartibda va necha marta?" degan savolga.

Tekshirib ko'ring: Bot har kelgan xabarda "bu foydalanuvchi bloklanganmi?" deb tekshiradi. Bloklanganlar — 50 000 kishi. Ularni massivdami yoki Set da saqlash kerak?

Javob

Set da. Tekshiruv har xabarda, ya'ni juda ko'p marta bo'ladi. Massivda har tekshiruv 50 000 tagacha taqqoslash, Set da — deyarli bir zumda.

7. Ko'p uchraydigan xatolar

7.1 Indeks bilan o'qish

turlar[0] — undefined, xatosiz. Tuzatish: [...turlar][0] yoki for...of.

7.2 Obyektlarni ichidagi ma'lumot bo'yicha takrorsiz qilish

new Set(bronlar) bir xil ko'rinishli obyektlarni tashlamaydi. Tuzatish: «Obyektlar: havola bo'yicha» bo'limidagi korilgan qolipi — kalit (id, telefon) bo'yicha.

7.3 Bitta satrni new Set ga berish

new Set("osh") — { 'o', 's', 'h' }. Tuzatish: new Set(["osh"]).

7.4 new siz chaqirish

js
const turlar = Set(["osh"]);
text
TypeError: Constructor Set requires 'new'

Tarjimasi: "Set konstruktori new ni talab qiladi". class sintaksisi darsidagi klasslar kabi. Tuzatish: new Set([...]).

7.5 flatMap Set ni ochmaydi

js
const teglar = [1].flatMap(() => new Set(["#uy", "#bozor"]));

console.log(teglar); // [ Set(2) { '#uy', '#bozor' } ]

flatMap faqat callback qaytargan massivni ochadi. Boshqa narsani — shu jumladan Set ni — bitta element qilib qo'yadi. Tuzatish: callback ichida massivga aylantiring: () => [...toplam]. Bu tuzoqqa «Vazifalar qadami» da duch kelasiz.

8. Mashqlar

1-mashq (oson): Bugun nimalar sotildi

Kunlik buyurtmalardan bugun sotilgan taom turlarini takrorsiz chiqaring va nechta tur ekanini ayting.

js
const buyurtmalar = [
  "osh", "choy", "manti", "osh", "choy", "lag'mon",
];

Natija: [ 'osh', 'choy', 'manti', "lag'mon" ] va 4 xil taom.

Yechim
js
const buyurtmalar = [
  "osh", "choy", "manti", "osh", "choy", "lag'mon",
];

const turlar = new Set(buyurtmalar);
console.log([...turlar]);
console.log(`${turlar.size} xil taom`);

Konsolda:

text
[ 'osh', 'choy', 'manti', "lag'mon" ]
4 xil taom

Sonni bilish uchun massivga aylantirish shart emas — size tayyor.

2-mashq (o'rta): Kim ikki marta bron qildi

Bron qilganlarning ismlari kelish tartibida berilgan. Ikki yoki undan ko'p marta bron qilganlarni, har birini bir marta, toping.

Ishora: ikkita Set — korilgan (bir marta uchraganlar) va takrorlar. Har ism uchun: korilgan da bo'lsa — takrorlar ga qo'shing, aks holda — korilgan ga.

js
const bronlar = [
  "Jasur", "Nodira", "Bobur", "Jasur", "Nodira", "Jasur",
];
Yechim
js
const bronlar = [
  "Jasur", "Nodira", "Bobur", "Jasur", "Nodira", "Jasur",
];

const korilgan = new Set();
const takrorlar = new Set();
for (const ism of bronlar) {
  if (korilgan.has(ism)) {
    takrorlar.add(ism);
  } else {
    korilgan.add(ism);
  }
}

console.log([...takrorlar]); // [ 'Jasur', 'Nodira' ]

Jasur uch marta uchradi, lekin takrorlar da bir marta — chunki u ham Set. Har ism uchun faqat ikkita has/add — massiv bilan indexOf qilganda har safar butun ro'yxatni aylanardik.

3-mashq (qiyin): Mijozlar bazasini tozalash

Mijozlar ro'yxatida bir odam bir necha marta yozilgan. Telefon raqami esa har xil ko'rinishda: bo'sh joyli va bo'sh joysiz. takrorsizMijozlar(royxat) funksiyasini yozing: telefonni bo'sh joylarsiz ko'rinishga keltirib, har raqamdan faqat birinchi mijoz qolsin.

Ishora: «Obyektlar: havola bo'yicha» bo'limidagi korilgan qolipi; kalit — telefon.replaceAll(" ", "") (Matnni o'zgartirish).

js
const mijozlar = [
  { ism: "Dilshod aka", telefon: "+998 90 000 00 01" },
  { ism: "Nodira", telefon: "+998900000002" },
  { ism: "Dilshod", telefon: "+998900000001" },
  { ism: "Nodira opa", telefon: "+998 90 000 00 02" },
  { ism: "Bobur", telefon: "+998 90 000 00 03" },
];
Yechim
js
function takrorsizMijozlar(royxat) {
  const korilgan = new Set();
  return royxat.filter((mijoz) => {
    const kalit = mijoz.telefon.replaceAll(" ", "");
    if (korilgan.has(kalit)) {
      return false;
    }
    korilgan.add(kalit);
    return true;
  });
}

const mijozlar = [
  { ism: "Dilshod aka", telefon: "+998 90 000 00 01" },
  { ism: "Nodira", telefon: "+998900000002" },
  { ism: "Dilshod", telefon: "+998900000001" },
  { ism: "Nodira opa", telefon: "+998 90 000 00 02" },
  { ism: "Bobur", telefon: "+998 90 000 00 03" },
];

const toza = takrorsizMijozlar(mijozlar);
const ismlar = toza.map((m) => m.ism);
console.log(ismlar); // [ 'Dilshod aka', 'Nodira', 'Bobur' ]
console.log(mijozlar.length); // 5

korilgan funksiya ichida yaratiladi — har chaqiruvda yangi, toza Set. Uni tashqarida yaratsangiz, ikkinchi chaqiruv birinchisining raqamlarini "ko'rilgan" deb hisoblardi. Asl ro'yxat o'zgarmadi: filter yangi massiv qaytaradi.

4-mashq: Vazifalar qadami — teglar takrorsiz

feature/teglar branch'ida davom etamiz (Map darsida ochilgan). Ikki muammoni toping. Quyidagi ikki vazifani qo'shing va teglar qatoriga qarang:

  • "Sabzi olish #bozor #bozor"
  • "Guruch olish #Bozor"

Qator Teglar: #bozor — 2, #Bozor — 1 ko'rsatadi. Lekin #bozor aslida bitta vazifada, #Bozor esa — o'sha teg, boshqa harf bilan yozilgan.

Talab: bitta vazifadagi teg bir marta sanalsin, katta-kichik harf farq qilmasin. Natija Teglar: #bozor — 2.

  1. teglariniOl(matn) endi Set qaytarsin — kichik harfdagi teglar, takrorsiz.
  2. VazifalarRoyxati dagi tegHisobi() metodini moslang. Ishora: «flatMap Set ni ochmaydi».
Yechim
js
function teglariniOl(matn) {
  return new Set(
    matn
      .toLowerCase()
      .split(" ")
      .filter((soz) => soz.length > 1 && soz.startsWith("#")),
  );
}

VazifalarRoyxati ichida:

js
tegHisobi() {
  return this.#vazifalar
    .flatMap((vazifa) => [...teglariniOl(vazifa.matn)])
    .reduce(
      (sanoq, teg) => sanoq.set(teg, (sanoq.get(teg) ?? 0) + 1),
      new Map(),
    );
}

Ikki o'zgarish:

  • teglariniOl — toLowerCase() (Matnni o'zgartirish) va natija new Set(...) ga o'raldi. Endi funksiya nomi va natijasi bir xil narsani aytadi: "vazifaning teglari to'plami".
  • tegHisobi da flatMap callback'i [...teglariniOl(...)] qaytaradi. Spread'siz flatMap har Set ni bitta element qilib qo'yardi, reduce esa Map ga Set obyektlarini kalit qilib yozardi. Qatorda [object Set] — 1 chiqardi — xatosiz.

Vazifa matnining o'zi o'zgarmaydi: ro'yxatda "Guruch olish #Bozor" qanday yozilgan bo'lsa, shunday ko'rinadi. Faqat hisob kichik harf bilan.

Node'da eski va yangi funksiyani yonma-yon sinang:

js
function eskiTeglar(matn) {
  return matn
    .split(" ")
    .filter((soz) => soz.length > 1 && soz.startsWith("#"));
}

function teglariniOl(matn) {
  return new Set(
    matn
      .toLowerCase()
      .split(" ")
      .filter((soz) => soz.length > 1 && soz.startsWith("#")),
  );
}

function hisobla(vazifalar, ol) {
  return vazifalar
    .flatMap((vazifa) => [...ol(vazifa.matn)])
    .reduce(
      (sanoq, teg) => sanoq.set(teg, (sanoq.get(teg) ?? 0) + 1),
      new Map(),
    );
}

const vazifalar = [
  { matn: "Sabzi olish #bozor #bozor" },
  { matn: "Guruch olish #Bozor" },
  { matn: "Non olish" },
];

console.log(hisobla(vazifalar, eskiTeglar));
console.log(hisobla(vazifalar, teglariniOl));
console.log(teglariniOl("Non olish").size);

Konsolda:

text
Map(2) { '#bozor' => 2, '#Bozor' => 1 }
Map(1) { '#bozor' => 2 }
0

Ikkinchi qator — talabdagi natija. Tegsiz vazifa bo'sh Set beradi, spread uni bo'sh massivga aylantiradi, flatMap esa bo'sh massivni shunchaki tashlab ketadi.

Brauzerda tekshiring:

  • Ochilganda teglar qatori yashirin, hisob "2 ta vazifa qoldi, 1 ta bajarildi" — avvalgidek.
  • Yuqoridagi ikki vazifani qo'shing — Teglar: #bozor — 2.
  • "Kitob o'qish #Uy #uy #UY" qo'shing — #bozor — 2, #uy — 1.
  • "Sabzi…" ni o'chiring — #bozor — 1, #uy — 1.

Commit: Vazifalar: teglar takrorsiz va kichik harfda (Set). Branch hali ochiq — keyingi darsda yakunlaymiz.

9. Real ishda

  • Ro'yxatlarni tozalash. Import qilingan mijozlar, email ro'yxatlari, CSV fayllar — takrorlarni olib tashlash ma'lumot bilan ishlashda har kuni uchraydi.
  • "Ko'rilganmi?" tekshiruvlari. Botda bloklangan foydalanuvchilar, saytda tanlangan filtrlar, o'yinda ochilgan yutuqlar — hammasi Set. Xarita yoki ijtimoiy tarmoq kabi "bog'lanishlar to'ri" bo'ylab yuradigan algoritmlar ham "qayerda bo'ldim?" ro'yxatini Set da saqlaydi (buni algoritmlar qismida ko'rasiz).
  • Ruxsatlar. Foydalanuvchi rollari va ruxsatlari ko'pincha Set: ruxsatlar.has("buyurtma:ochirish").
  • React va kutubxonalar. React — interfeys yasash kutubxonasi, kursda alohida o'rganamiz. Unda va boshqa kutubxonalarda bir nechta qatorni tanlash imkoniyati (checkbox'li jadval) tanlangan id'larni Set da saqlaydi — qo'shish, olib tashlash va tekshirish bir zumda.
  • Intervyu. "Massivdan takrorlarni olib tashlang" — eng tez-tez beriladigan topshiriq. Kutilgan javob — [...new Set(arr)] va uning obyektlarda ishlamasligi.

Xulosa

  • Set — har qiymat bir marta: add, has, delete, clear, size. Takror add jimgina e'tiborsiz qoladi.
  • Takrorlarni olib tashlash: [...new Set(massiv)], tartib — birinchi uchrash.
  • Solishtirish — SameValueZero: NaN o'ziga teng, obyektlar havola bo'yicha. Obyektlarni kalit bo'yicha tozalash — korilgan Set i bilan.
  • Set da indeks va massiv metodlari yo'q — avval [...set]. flatMap Set ni ochmaydi.
  • Ko'p marta "bormi?" deb so'ralsa — Set va has: katta ro'yxatda includes dan minglab marta tez.

Keyingi dars: Set to'plam metodlari — ikki to'plamni birlashtirish, kesishmasini va farqini topish endi bitta metod bilan: union, intersection, difference va boshqalar.

Manbalar

  • MDN: "Set", "Set.prototype.has()" — developer.mozilla.org
  • ECMAScript 2025 Language Specification: "Set Objects" — tc39.es/ecma262
  • web-features 3.40: set — github.com/web-platform-dx/web-features
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JavaScript Set: faqat takrorlanmas qiymatlar to'plami — IlmHamroh