IlmHamroh
JavaScript Full-stack/10-qism. JavaScript chuqur46/65-dars18 daqiqa
Mundarija (31)

JavaScript Set metodlari: union, intersection, difference va boshqalar

Qisqacha: ES2025 dan Set da yettita to'plam metodi bor. To'rttasi yangi Set qaytaradi: a.union(b) — ikkalasidagi hammasi, a.intersection(b) — ikkalasida ham borlari, a.difference(b) — a da bor, b da yo'qlari, a.symmetricDifference(b) — faqat bittasida borlari. Uchtasi true/false beradi: isSubsetOf, isSupersetOf, isDisjointFrom. Asl to'plamlar o'zgarmaydi.

Bu darsda

  • Ikki to'plamning birlashmasi, kesishmasi va farqini bitta metod bilan hisoblay olasiz.
  • "Hammasi bormi?", "umumiy narsa bormi?" savollariga isSubsetOf, isSupersetOf, isDisjointFrom bilan javob bera olasiz.
  • Metodga qanday argument berish mumkinligini (Set, Map) va massiv nega xato berishini bilasiz.
  • Bu metodlar qaysi brauzerlarda ishlashini va eski muhit uchun zaxira yozishni bilasiz.
  • vazifalar da "yopilgan teglar" ni ko'rsatasiz va teglar imkoniyatini yakunlaysiz.

Oldin bilishingiz kerak: Set, Map, filter, Massivda qidirish va tekshirish.

1. Nega bu kerak?

«Bahor»da dushanba va seshanba kunlari qaysi taomlar sotilganini yozib boramiz:

js
const dushanba = new Set(["osh", "manti", "choy"]);
const seshanba = new Set(["choy", "osh", "somsa"]);

Jasur aka to'rtta savol beradi:

  1. Ikki kunda jami qaysi taomlar sotildi?
  2. Qaysilari ikkala kunda ham sotildi?
  3. Dushanba sotilib, seshanba sotilmaganlari qaysi?
  4. Faqat bitta kunda sotilganlari qaysi?

Set darsida o'rganganlaringiz bilan javob berish mumkin. Masalan, ikkinchi savol:

js
const dushanba = new Set(["osh", "manti", "choy"]);
const seshanba = new Set(["choy", "osh", "somsa"]);

const ikkalasida = new Set(
  [...dushanba].filter((taom) => seshanba.has(taom)),
);
console.log(ikkalasida); // Set(2) { 'osh', 'choy' }

Ishlaydi. Lekin har savol uchun spread, filter, has va yana new Set — to'rt qadam. Uchinchi savolda !seshanba.has bo'ladi, to'rtinchisida esa ikki yo'nalishni birlashtirish kerak. Kod uzayadi, xato qilish oson: ! ni unutish yoki to'plamlarni almashtirib yuborish.

2025-yilda JavaScript standartiga (ES2025) to'plamlar bilan ishlaydigan yettita tayyor metod qo'shildi. Yuqoridagi to'rt savolning har biri endi bitta metod.

2. To'rt amal — rasmda

To'plamlar ustida amal — ikki to'plamdan uchinchisini yasash qoidasi. Matematikada ular ustma-ust tushgan doiralar bilan ko'rsatiladi — bunday rasmni Venn diagrammasi deyishadi, maktab matematikasidan tanish bo'lishi mumkin. Har rasmda chap doira — dushanba (D), o'ng doira — seshanba (S). Bo'yalgan qism — metod qaytaradigan natija:

html
<style>
  .venn {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 0.75rem;
    font: 0.95rem/1.4 system-ui, sans-serif;
    color: #1f2a24;
  }
  .venn figure { min-width: 0; margin: 0; text-align: center; }
  .venn svg { width: 100%; max-width: 10rem; }
  .venn .t { fill: #9fd3b5; }
  .venn .oq { fill: #fff; }
  .venn .c { fill: none; stroke: #1f6f4a; stroke-width: 2; }
  .venn text { font: bold 14px system-ui, sans-serif; fill: #1f2a24; }
  .venn code { font-size: 0.85rem; overflow-wrap: anywhere; }
</style>
<div class="venn">
  <figure>
    <svg viewBox="0 0 160 100" role="img"
         aria-label="Ikkala doira to'liq bo'yalgan">
      <circle class="t" cx="62" cy="50" r="38"/>
      <circle class="t" cx="98" cy="50" r="38"/>
      <circle class="c" cx="62" cy="50" r="38"/>
      <circle class="c" cx="98" cy="50" r="38"/>
      <text x="38" y="55">D</text><text x="112" y="55">S</text>
    </svg>
    <figcaption><code>D.union(S)</code><br>hammasi</figcaption>
  </figure>
  <figure>
    <svg viewBox="0 0 160 100" role="img"
         aria-label="Faqat doiralar ustma-ust tushgan qism bo'yalgan">
      <defs><clipPath id="k2">
        <circle cx="62" cy="50" r="38"/>
      </clipPath></defs>
      <circle class="t" cx="98" cy="50" r="38" clip-path="url(#k2)"/>
      <circle class="c" cx="62" cy="50" r="38"/>
      <circle class="c" cx="98" cy="50" r="38"/>
      <text x="38" y="55">D</text><text x="112" y="55">S</text>
    </svg>
    <figcaption><code>D.intersection(S)</code><br>
      ikkalasida</figcaption>
  </figure>
  <figure>
    <svg viewBox="0 0 160 100" role="img"
         aria-label="Chap doiraning o'ngga tegmagan qismi bo'yalgan">
      <circle class="t" cx="62" cy="50" r="38"/>
      <circle class="oq" cx="98" cy="50" r="38"/>
      <circle class="c" cx="62" cy="50" r="38"/>
      <circle class="c" cx="98" cy="50" r="38"/>
      <text x="38" y="55">D</text><text x="112" y="55">S</text>
    </svg>
    <figcaption><code>D.difference(S)</code><br>
      D da bor, S da yo'q</figcaption>
  </figure>
  <figure>
    <svg viewBox="0 0 160 100" role="img"
         aria-label="Ikki doira bo'yalgan, umumiy qism oq">
      <defs><clipPath id="k4">
        <circle cx="62" cy="50" r="38"/>
      </clipPath></defs>
      <circle class="t" cx="62" cy="50" r="38"/>
      <circle class="t" cx="98" cy="50" r="38"/>
      <circle class="oq" cx="98" cy="50" r="38" clip-path="url(#k4)"/>
      <circle class="c" cx="62" cy="50" r="38"/>
      <circle class="c" cx="98" cy="50" r="38"/>
      <text x="38" y="55">D</text><text x="112" y="55">S</text>
    </svg>
    <figcaption><code>D.symmetricDifference(S)</code><br>faqat
      bittasida</figcaption>
  </figure>
</div>

Ikki doira ustma-ust tushgan o'rta qism — "ikkala kunda ham sotilgan" taomlar. Uchinchi rasmga alohida qarang: difference faqat bitta tomonni beradi. Shuning uchun D.difference(S) va S.difference(D) — har xil natija.

3. Yangi Set qaytaradigan to'rt metod

3.1 union — birlashma

Birlashma (union) — ikki to'plamdagi hamma qiymat, har biri bir marta:

js
const dushanba = new Set(["osh", "manti", "choy"]);
const seshanba = new Set(["choy", "osh", "somsa"]);

console.log(dushanba.union(seshanba));
// Set(4) { 'osh', 'manti', 'choy', 'somsa' }

Tartib: avval dushanba dagilar, keyin seshanba dan yangilari. "choy" va "osh" ikkinchi marta qo'shilmadi. Bu — new Set([...dushanba, ...seshanba]) ning qisqa va aniq yozuvi.

3.2 intersection — kesishma

Kesishma (intersection) — ikkala to'plamda ham bor qiymatlar:

js
const dushanba = new Set(["osh", "manti", "choy"]);
const seshanba = new Set(["choy", "osh", "somsa"]);

const umumiy = dushanba.intersection(seshanba);
console.log(umumiy); // Set(2) { 'osh', 'choy' }

«Nega bu kerak?» bo'limidagi to'rt qadamli kod — bitta chaqiruv.

Bitta nozik joy bor: natija tartibi. Metod tezroq ishlashi uchun kichikroq to'plamni aylanadi. To'plamlar teng bo'lsa — chapdagini. Agar argument kichikroq bo'lsa, natija uning tartibida chiqadi:

js
const katta = new Set([1, 2, 3, 4]);
const kichik = new Set([3, 2]);

console.log(katta.intersection(kichik)); // Set(2) { 3, 2 }

Natija { 2, 3 } emas, { 3, 2 } — kichik ning tartibi. Odatda bu muhim emas. Tartib muhim bo'lsa (masalan, ekranga chiqarishda), natijani massivga aylantirib, o'zingiz saralang.

3.3 difference — farq

Farq (difference) — birinchisida bor, ikkinchisida yo'q qiymatlar:

js
const dushanba = new Set(["osh", "manti", "choy"]);
const seshanba = new Set(["choy", "osh", "somsa"]);

console.log(dushanba.difference(seshanba)); // Set(1) { 'manti' }
console.log(seshanba.difference(dushanba)); // Set(1) { 'somsa' }

Bu metodda tartib hal qiluvchi: "kimdan kim ayiriladi". Sonlardagi ayirish kabi: 5 - 3 va 3 - 5 — har xil. O'qishda yordam beradigan gap: "a.difference(b) — a dan b dagilarni olib tashla".

3.4 symmetricDifference — simmetrik farq

Simmetrik farq (symmetric difference) — faqat bittasida bor qiymatlar. Umumiylar chiqarib tashlanadi:

js
const dushanba = new Set(["osh", "manti", "choy"]);
const seshanba = new Set(["choy", "osh", "somsa"]);

console.log(dushanba.symmetricDifference(seshanba));
// Set(2) { 'manti', 'somsa' }

Bu ikki farqning birlashmasi: a.difference(b).union(b.difference(a)). Nomidagi "simmetrik" so'zi shuni bildiradi: to'plamlarni almashtirsangiz ham, qiymatlar bir xil chiqadi (tartibi farq qilishi mumkin).

3.5 Asl to'plamlar o'zgarmaydi

To'rttala metod ham yangi Set qaytaradi. dushanba va seshanba qanday bo'lsa, shunday qoladi:

js
const dushanba = new Set(["osh", "manti"]);
const seshanba = new Set(["somsa"]);

const hammasi = dushanba.union(seshanba);
console.log(dushanba.size, hammasi.size); // 2 3
console.log(hammasi === dushanba); // false

Bu Nusxa bilan o'zgartirish darsidagi toSorted g'oyasi: natija — yangi qiymat, asl ma'lumot buzilmaydi. Natijalarni zanjir qilish ham mumkin: a.union(b).difference(c).

3.6 Ikkitadan ko'p to'plam

Metodlar har safar ikki to'plam bilan ishlaydi. Uch kun, bir hafta yoki bir oy bo'lsa-chi? reduce yordam beradi: u to'plamlarni juft-juft "yig'ib" boradi.

js
const hafta = [
  new Set(["osh", "manti", "choy"]),
  new Set(["choy", "osh", "somsa"]),
  new Set(["osh", "choy", "lag'mon"]),
];

const harKuni = hafta.reduce((a, b) => a.intersection(b));
const kamidaBirKun = hafta.reduce((a, b) => a.union(b));

console.log(harKuni); // Set(2) { 'osh', 'choy' }
console.log(kamidaBirKun.size); // 5

Boshlang'ich qiymat berilmadi, shuning uchun akkumulyator — birinchi kunning to'plami. Har qadamda u keyingi kun bilan kesishadi (yoki birlashadi). Natija — har kuni sotilgan ikki taom va hafta davomida sotilgan besh xil taom.

Ehtiyot bo'ling: bo'sh massivda boshlang'ich qiymatsiz reduce xato beradi (reduce darsidagi tuzoq). Birlashma uchun xavfsiz boshlang'ich qiymat bor — bo'sh to'plam: hafta.reduce((a, b) => a.union(b), new Set()). Kesishma uchun esa bunday qiymat yo'q: bo'sh to'plam bilan kesishma doim bo'sh. Shuning uchun kesishmadan oldin massiv bo'sh emasligini tekshiring.

Tekshirib ko'ring: A = {1, 2, 3}, B = {3, 4}. A.difference(B) va A.symmetricDifference(B) nima qaytaradi?

Javob

A.difference(B) — {1, 2}: A dan B dagi 3 olib tashlandi. A.symmetricDifference(B) — {1, 2, 4}: umumiy 3 dan tashqari hammasi. Farq 4 da: difference faqat A tomonni ko'radi, simmetrik farq — ikkala tomonni.

O'zingiz to'ldiring. new Set([1, 2]).union(new Set([2, 3])).size — [:3]. new Set([1, 2]).intersection(new Set([2, 3])).size — [:1].

4. "Ha yoki yo'q" beradigan uch metod

Ba'zan yangi to'plam emas, faqat javob kerak. Bunga uchta metod bor — har biri true yoki false qaytaradi.

4.1 isSubsetOf va isSupersetOf

Qism to'plam (subset) — hamma qiymatlari boshqa to'plamda ham bor to'plam. a.isSubsetOf(b) — "a ning hammasi b ichidami?". isSupersetOf — xuddi shu savol, teskari tomondan: "a b ning hammasini o'z ichiga oladimi?".

Real misol — ruxsatlar. Otabek kassa dasturida buyurtmani bekor qilmoqchi. Buning uchun ikki ruxsat kerak:

js
const kerakli = new Set(["buyurtma:korish", "buyurtma:bekor"]);
const otabek = new Set(["buyurtma:korish", "buyurtma:yaratish"]);
const jasurAka = new Set([
  "buyurtma:korish",
  "buyurtma:yaratish",
  "buyurtma:bekor",
]);

console.log(kerakli.isSubsetOf(otabek)); // false
console.log(kerakli.isSubsetOf(jasurAka)); // true
console.log(jasurAka.isSupersetOf(kerakli)); // true

Otabekda "bekor qilish" ruxsati yo'q — false. Jasur akada hammasi bor — true. Uchinchi qator ikkinchisining aynan o'zi, faqat boshqa tomondan o'qiladi. Qaysi biri o'qishga qulayroq bo'lsa, shuni yozing.

Ikki chegaraviy holat:

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

console.log(new Set().isSubsetOf(menyu)); // true
console.log(menyu.isSubsetOf(menyu)); // true

Bo'sh to'plam har qanday to'plamning qismi: "hamma qiymatlari bor" sharti buzilmaydi, chunki qiymatning o'zi yo'q. Bu every dagi qoida bilan bir xil: [].every(...) — doim true. To'plam o'zining qismi ham.

4.2 isDisjointFrom — umumiy narsa yo'qmi?

Kesishmaydigan (disjoint) to'plamlar — bitta ham umumiy qiymati yo'q to'plamlar. Bobur yong'oq va kunjutga allergik. Taom unga mosmi?

js
const allergiya = new Set(["yong'oq", "kunjut"]);
const somsa = new Set(["un", "go'sht", "piyoz", "kunjut"]);
const manti = new Set(["un", "go'sht", "piyoz"]);

console.log(somsa.isDisjointFrom(allergiya)); // false
console.log(manti.isDisjointFrom(allergiya)); // true

Somsada kunjut bor — false, mos emas. Mantida umumiy narsa yo'q — true. Bu a.intersection(b).size === 0 bilan bir xil, lekin tezroq: metod birinchi umumiy qiymatni topishi bilan to'xtaydi va yangi to'plam yasamaydi.

Tekshirib ko'ring: new Set(["osh"]).isSupersetOf(new Set()) nima qaytaradi?

Javob

true. Savol: "{osh} bo'sh to'plamning hamma qiymatlarini o'z ichiga oladimi?" Bo'sh to'plamda qiymat yo'q — talab bajarildi. Bu «Ikki chegaraviy holat» dagi new Set().isSubsetOf(...) ning teskari tomondan o'qilishi.

4.3 Qaysi savolga qaysi metod

Metod nomini eslab qolish qiyin bo'lsa, savolni o'zbekcha ayting — u metodni o'zi ko'rsatadi:

Savol Metod Natija
"Ikkalasida jami nima bor?" union Set
"Ikkalasida ham nima bor?" intersection Set
"A da bor, B da yo'q nima?" difference Set
"Faqat bittasida nima bor?" symmetricDifference Set
"A ning hammasi B da bormi?" isSubsetOf boolean
"A da B ning hammasi bormi?" isSupersetOf boolean
"Umumiy narsa yo'qmi?" isDisjointFrom boolean

Savolda "nima?" bo'lsa — javob to'plam. "-mi?" bo'lsa — javob true yoki false. Bu kursdagi predikat nomlari qoidasi bilan bir xil: mosmi, arzonmi ham "-mi" bilan tugaydi va boolean qaytaradi.

5. Argument sifatida nima berish mumkin

5.1 Massiv — xato

Eng tabiiy urinish — massivni berish:

js
const menyu = new Set(["osh", "manti"]);
const yangi = menyu.union(["somsa"]);
text
TypeError: The .size property is NaN

Tarjimasi: ".size xususiyati — NaN". Xabar g'alati, chunki massiv haqida hech narsa demaydi. Sababi: metod argumentdan size ni so'radi. Massivda size yo'q (length bor), undefined songa aylanib NaN berdi. Metod "bu to'plam emas" deb to'xtadi. Tuzatish: menyu.union(new Set(["somsa"])).

5.2 "To'plamga o'xshash" qiymat

Metodlar argumentning turini tekshirmaydi. Ular faqat uch narsani so'raydi: size (son), has (metod) va keys (metod). Shu uchtasi bor qiymat — to'plamga o'xshash (set-like). Set dan tashqari Map ham shunday — uning kalitlari ishlatiladi:

js
const menyu = new Set(["osh", "manti"]);
const narxlar = new Map([
  ["somsa", 8000],
  ["osh", 35000],
]);

const hammasi = menyu.union(narxlar);
console.log(hammasi); // Set(3) { 'osh', 'manti', 'somsa' }
console.log(menyu.difference(narxlar)); // Set(1) { 'manti' }

Qulay: narxi yozilgan taomlar Map da bo'lsa, ularni [...narxlar.keys()] qilib Set ga aylantirish shart emas. Natija esa doim Set.

Tekshirib ko'ring: narxlar — Map: kalitlari "osh", "manti", "choy". new Set(["osh", "manti"]).isSubsetOf(narxlar) nima qaytaradi?

Javob

true. Map argument bo'lganda faqat uning kalitlari hisobga olinadi. "osh" ham, "manti" ham kalitlar orasida bor — demak to'plam Map kalitlarining qismi. Narxlar (qiymatlar) bu savolda umuman ishtirok etmaydi.

6. Qayerda ishlaydi

Baseline ma'lumotiga ko'ra yettita metod brauzerlarga shu versiyalardan kelgan: Chrome va Edge 122, Firefox 127, Safari 17 (iOS 17). Hammasida birga ishlay boshlagan sana — 2024-yil 11-iyun. Shu kundan ular Baseline'ning "yangi" (newly available) darajasida: hamma asosiy brauzerning so'nggi versiyasida bor.

Keyingi daraja — "keng tarqalgan" (widely available). U yangi imkoniyat hamma asosiy brauzerda paydo bo'lganidan 30 oy o'tgach beriladi. Bu metodlar uchun u 2026-yil dekabr oyiga to'g'ri keladi — hozir (oktyabr) hali yo'q. Amaliy ma'nosi: yangilanmagan eski telefonlarda, masalan iOS 16 da, TypeError: a.union is not a function chiqadi.

Node'da: biz Node 24 da sinab ko'rdik — hammasi ishlaydi; Node 22 da ham bor.

Eski muhit uchun zaxira — bitta qatorli funksiyalar. Ular «Nega bu kerak?» bo'limidagi usul:

js
function kesishma(a, b) {
  return new Set([...a].filter((q) => b.has(q)));
}

function farq(a, b) {
  return new Set([...a].filter((q) => !b.has(q)));
}

const d = new Set(["osh", "manti", "choy"]);
const s = new Set(["choy", "osh", "somsa"]);

console.log(kesishma(d, s)); // Set(2) { 'osh', 'choy' }
console.log(d.intersection(s)); // Set(2) { 'osh', 'choy' }
console.log(farq(d, s)); // Set(1) { 'manti' }
console.log(d.difference(s)); // Set(1) { 'manti' }

O'z nusxamiz va haqiqiy metod bir xil natija berdi. Endi metodning ichida nima borligini ham bilasiz: aylanish va has. Haqiqiy metod qo'shimcha ravishda kichikroq to'plamni tanlaydi va argument turini tekshiradi.

7. Ko'p uchraydigan xatolar

7.1 Massivni argument qilish

menyu.union(["somsa"]) — TypeError: The .size property is NaN. Tuzatish: new Set([...]) ga o'rang.

7.2 difference da tomonni adashtirish

seshanba.difference(dushanba) o'rniga dushanba.difference(seshanba) yozildi — xatosiz, lekin boshqa javob. Tuzatish: "chapdagidan o'ngdagini olib tashla" deb o'qing. Ikkala tomon kerak bo'lsa — symmetricDifference.

7.3 Natija asl to'plamga yozildi deb kutish

js
const menyu = new Set(["osh"]);
menyu.union(new Set(["manti"]));

console.log(menyu.size); // 1

union yangi Set qaytardi, biz uni hech qayerga saqlamadik — natija yo'qoldi. Tuzatish: const hammasi = menyu.union(...). Asl to'plamning o'zini kengaytirish kerak bo'lsa — eski usul: add.

7.4 Ma'lumoti bir xil obyektlar

To'plam metodlari ham Set dagi qoida bilan solishtiradi: obyektlar havola bo'yicha. Ikki xil { id: 1 } obyekti intersection da uchrashmaydi. Tuzatish: id yoki boshqa primitiv kalitlar to'plami bilan ishlang.

8. Mashqlar

1-mashq (oson): Ikki kunlik hisobot

«Nega bu kerak?» bo'limidagi dushanba va seshanba to'plamlari bilan Jasur akaning to'rt savoliga javob bering. Har javobni massiv ko'rinishida chiqaring.

Yechim
js
const dushanba = new Set(["osh", "manti", "choy"]);
const seshanba = new Set(["choy", "osh", "somsa"]);

console.log([...dushanba.union(seshanba)]);
console.log([...dushanba.intersection(seshanba)]);
console.log([...dushanba.difference(seshanba)]);
console.log([...dushanba.symmetricDifference(seshanba)]);

Konsolda:

text
[ 'osh', 'manti', 'choy', 'somsa' ]
[ 'osh', 'choy' ]
[ 'manti' ]
[ 'manti', 'somsa' ]

Har savolga bitta metod. [...] — natijani massivga aylantirish, chiqishi o'qishga qulay bo'lishi uchun.

2-mashq (o'rta): Bobur uchun menyu

Har taomning tarkibi Map da berilgan: kalit — taom nomi, qiymat — tarkib to'plami. Bobur yong'oq va kunjutga allergik. Unga mos taomlar nomlari massivini qaytaring.

Ishora: [...menyu] juftliklarini filter qiling — shart isDisjointFrom; so'ng map bilan nomlarni oling.

js
const menyu = new Map([
  ["osh", new Set(["guruch", "go'sht", "sabzi"])],
  ["somsa", new Set(["un", "go'sht", "kunjut"])],
  ["holva", new Set(["un", "shakar", "yong'oq"])],
  ["manti", new Set(["un", "go'sht", "piyoz"])],
]);
const allergiya = new Set(["yong'oq", "kunjut"]);
Yechim
js
const menyu = new Map([
  ["osh", new Set(["guruch", "go'sht", "sabzi"])],
  ["somsa", new Set(["un", "go'sht", "kunjut"])],
  ["holva", new Set(["un", "shakar", "yong'oq"])],
  ["manti", new Set(["un", "go'sht", "piyoz"])],
]);
const allergiya = new Set(["yong'oq", "kunjut"]);

const mos = [...menyu]
  .filter(([, tarkib]) => tarkib.isDisjointFrom(allergiya))
  .map(([nom]) => nom);

console.log(mos); // [ 'osh', 'manti' ]

([, tarkib]) — destructuring'da birinchi elementni (nomni) tashlab ketdik, chunki shart uchun faqat tarkib kerak (Massiv destructuring). Somsa kunjut, holva yong'oq tufayli tushib qoldi.

3-mashq (qiyin): Bron va kelganlar

Kechqurun Otabek ikki ro'yxatni solishtiradi: bron qilganlar va haqiqatda kelganlar. bronHisoboti(bronlar, kelganlar) funksiyasini yozing. U ikki massiv oladi va obyekt qaytaradi:

  • kelmadi — bron qilib kelmaganlar;
  • bronsiz — bronsiz kelganlar;
  • hammasiKeldimi — bron qilganlarning hammasi keldimi (true/false).

Massivlarni avval Set ga aylantiring. Bo'sh bron ro'yxatini ham sinang.

Yechim
js
function bronHisoboti(bronlar, kelganlar) {
  const b = new Set(bronlar);
  const k = new Set(kelganlar);
  return {
    kelmadi: [...b.difference(k)],
    bronsiz: [...k.difference(b)],
    hammasiKeldimi: b.isSubsetOf(k),
  };
}

const bronlar = ["Malika", "Dilshod aka", "Nodira"];
const kelganlar = ["Dilshod aka", "Bobur", "Malika"];

console.log(bronHisoboti(bronlar, kelganlar));
console.log(bronHisoboti([], kelganlar).hammasiKeldimi);

Konsolda:

text
{ kelmadi: [ 'Nodira' ], bronsiz: [ 'Bobur' ], hammasiKeldimi: false }
true

Ikki difference — ikki yo'nalish: biri bronlardan kelganlarni, ikkinchisi kelganlardan bronlarni olib tashlaydi. Bron bo'lmasa, hammasiKeldimi — true: bo'sh to'plam har qanday to'plamning qismi. Biznes nuqtai nazaridan ham to'g'ri — kutilgan odam yo'q, demak hech kim kelmay qolmadi.

4-mashq: Vazifalar qadami — yopilgan teglar va branch'ni yakunlash

feature/teglar branch'idagi oxirgi qadam. Teglar qatori hozir har tegning nechta vazifada uchrashini ko'rsatadi. Yangi talab: hamma vazifasi bajarilgan teglarni alohida ayting — bu "yopilgan" ish. Masalan, #bozor teglari bor ikki vazifa ham belgilangan bo'lsa:

Teglar: #bozor — 2, #uy — 1. Yopilgan: #bozor

Yopilgan teg yo'q bo'lsa — qator avvalgidek, qo'shimchasiz.

  1. tegToplami(vazifalar) — berilgan vazifalardagi barcha teglar Set i. Oddiy funksiya, teglariniOl yonida.
  2. yopilganTeglar() — VazifalarRoyxati ning yangi metodi: bajarilgan vazifalar teglaridan faol vazifalar teglarini ayiring.
  3. render() uzayib ketmasin: teglar qatorini alohida teglarniYoz() funksiyasiga chiqaring va unga qo'shimchani qo'shing.
Yechim

teglariniOl dan keyin, klassdan oldin:

js
function tegToplami(vazifalar) {
  return new Set(
    vazifalar.flatMap((vazifa) => [...teglariniOl(vazifa.matn)]),
  );
}

VazifalarRoyxati ichida, tegHisobi dan keyin:

js
yopilganTeglar() {
  const bajarilgan = this.#vazifalar.filter((v) => v.bajarildi);
  const faol = this.#vazifalar.filter((v) => !v.bajarildi);
  return tegToplami(bajarilgan).difference(tegToplami(faol));
}

"4. Chizish" da, render() dan oldin — yangi funksiya. render() dagi teglar qatori uchta qator o'rniga bitta chaqiruv bo'ladi: teglarniYoz();.

js
function teglarniYoz() {
  const sanoq = holat.vazifalar.tegHisobi();
  const yopilgan = [...holat.vazifalar.yopilganTeglar()];
  const qoshimcha =
    yopilgan.length > 0 ? `. Yopilgan: ${yopilgan.join(", ")}` : "";
  teglarQatori.hidden = sanoq.size === 0;
  matnniYoz(
    teglarQatori,
    `Teglar: ${teglarMatni(sanoq)}${qoshimcha}`,
  );
}

Nega difference? "Yopilgan teg" — bajarilgan vazifada bor, lekin birorta faol vazifada yo'q teg. Bu so'zma-so'z difference ning ta'rifi. Faol vazifada ham uchrasa, teg hali ochiq — u natijaga tushmaydi.

Node'da chegaraviy holatlar bilan sinang:

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

function tegToplami(vazifalar) {
  return new Set(
    vazifalar.flatMap((vazifa) => [...teglariniOl(vazifa.matn)]),
  );
}

function yopilganTeglar(vazifalar) {
  const bajarilgan = vazifalar.filter((v) => v.bajarildi);
  const faol = vazifalar.filter((v) => !v.bajarildi);
  return tegToplami(bajarilgan).difference(tegToplami(faol));
}

const vazifalar = [
  { matn: "Sabzi olish #bozor", bajarildi: true },
  { matn: "Guruch olish #bozor #uy", bajarildi: true },
  { matn: "Gilam yuvish #uy", bajarildi: false },
];

console.log(yopilganTeglar(vazifalar));
console.log(yopilganTeglar(vazifalar.slice(0, 2)));
console.log(yopilganTeglar([]).size);

Konsolda:

text
Set(1) { '#bozor' }
Set(2) { '#bozor', '#uy' }
0

#uy birinchi holatda yopilmagan — "Gilam yuvish" hali faol. Faol vazifa olib tashlanganda u ham yopildi. Bo'sh ro'yxatda natija bo'sh — qatorga qo'shimcha chiqmaydi.

Brauzerda tekshiring:

  • Ochilganda — teglar qatori yashirin, qolgan hamma narsa avvalgidek.
  • "Sabzi olish #bozor" va "Guruch olish #bozor #uy" qo'shing — Teglar: #bozor — 2, #uy — 1.
  • Avval "Guruch…" ni belgilang — … Yopilgan: #uy: #bozor hali "Sabzi…" da ochiq.
  • "Sabzi…" ni ham belgilang — … Yopilgan: #bozor, #uy. "Guruch…" ni qaytaring — Yopilgan yo'qoladi: ikkala teg yana faol vazifada.
  • «Faol» filtrida ham qator bir xil: teglar butun ro'yxatdan hisoblanadi, filtrdan emas.

Yakunlash. Uch darsda branch'da uch commit to'plandi. Oxirgisini qo'shib, main ga birlashtiring:

bash
git add assets/js/vazifalar.js
git commit -m "Vazifalar: yopilgan teglar (Set.difference)"
git switch main
git merge feature/teglar
git branch -d feature/teglar
git push
Dars Teglarga nima qo'shildi
Map teglariniOl, royxatda tegHisobi() (Map sanog'i), #teglar qatori
Set teglar takrorsiz va kichik harfda (Set)
shu dars tegToplami, royxatda yopilganTeglar() (difference), teglarniYoz()

Set.difference iOS 17 dan eski telefonlarda yo'q («Qayerda ishlaydi»). Sizning foydalanuvchilaringiz orasida bunday telefonlar bo'lsa — yopilganTeglar da farq zaxira funksiyasini ishlating.

9. Real ishda

  • Ruxsatlar va rollar. "Foydalanuvchida kerakli ruxsatlarning hammasi bormi?" — isSubsetOf. Admin panellar, API'lar, fayl tizimlari shunday tekshiradi.
  • Sinxronlash. Serverdagi va telefondagi ro'yxatni solishtirish: difference — nimani yuklash, teskari difference — nimani o'chirish kerak. Kontaktlar, sevimlilar, savat.
  • Filtrlar. Internet do'konda "hamma tanlangan teglar bor mahsulotlar" — isSubsetOf; "kamida bittasi bor" — isDisjointFrom ning teskarisi.
  • Ma'lumot tahlili. "Ikki oyda ham xarid qilgan mijozlar" (intersection), "ketib qolgan mijozlar" (difference) — marketing hisobotlarining asosi. SQL'da xuddi shu amallar UNION, INTERSECT, EXCEPT deb ataladi — bazalarni o'rganganda tanish bo'ladi.
  • Eski kod. 2024-yilgacha bu amallar uchun Lodash kutubxonasining (tayyor yordamchi funksiyalar to'plami, juda ko'p loyihada bor) _.union, _.intersection, _.difference funksiyalari ishlatilardi — ular massivlar bilan ishlaydi. Eski loyihalarda ularni ko'p uchratasiz. Yangi kodda o'rnatilgan Set metodlari yetarli, qo'shimcha kutubxona kerak emas.
  • Intervyu. "Ikki massivning kesishmasini toping" — klassik topshiriq. Endi ikki javobni bilasiz: filter + has (har joyda ishlaydi) va intersection (ES2025).

Xulosa

  • union — hammasi, intersection — ikkalasida, difference — chapda bor o'ngda yo'q, symmetricDifference — faqat bittasida. Hammasi yangi Set qaytaradi.
  • isSubsetOf, isSupersetOf, isDisjointFrom — true/false. Bo'sh to'plam har qanday to'plamning qismi.
  • Argument — to'plamga o'xshash qiymat (size, has, keys): Set yoki Map. Massiv — TypeError: The .size property is NaN.
  • difference da tomon muhim. intersection natijasi kichikroq to'plam tartibida bo'lishi mumkin.
  • Baseline 2024-yil iyunidan (Chrome 122, Firefox 127, Safari 17); eski muhitda — filter + has zaxirasi.

Keyingi dars: WeakMap, WeakSet, WeakRef va FinalizationRegistry — obyektni xotiradan tozalanishiga to'sqinlik qilmaydigan "kuchsiz" to'plamlar va ular qachon kerakligi.

Manbalar

  • MDN: "Set" — "Set composition" bo'limi; "Set.prototype.union()", "Set.prototype.isDisjointFrom()" — developer.mozilla.org
  • ECMAScript 2025 Language Specification: "Set.prototype.intersection", "GetSetRecord" — tc39.es/ecma262
  • web-features 3.40: set-methods — 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 metodlari: union, intersection, difference va boshqalar — IlmHamroh