25 август 2025

Massiv usullari

Massivlar juda ko’p usullarni taqdim etadi. Ishlarni engillashtirish uchun ushbu bobda ular guruhlarga bo’lingan.

Elementlarni qo’shish/olib tashlash

Biz allaqachon elementlarni boshidan yoki oxiridan qo’shib olib tashlaydigan usullarni bilamiz:

  • arr.push(...items) – oxiriga narsalarni qo’shadi,
  • arr.pop() – oxiridan elementni ajratib oladi,
  • arr.shift() – boshidan elementni ajratib oladi,
  • arr.unshift(...items) – elementlarni boshiga qo’shadi.

Mana boshqalar.

splice

Massivdan elementni qanday o’chirish mumkin?

Massivlar obyektlardir, shuning uchun biz delete dan foydalanishga urinib ko’rishimiz mumkin:

let arr = ["I", "go", "home"];

delete arr[1]; // "go" olib tashlash

alert(arr[1]); // undefined

// hozir arr = ["I",  , "home"];
alert(arr.length); // 3

Element o’chirildi, ammo massivda hali ham 3 ta element mavjud, biz buni ko’rishimiz mumkin arr.length == 3.

Bu tabiiy, chunki obj.key ni o’chirish key yordamida qiymatni olib tashlaydi. Hammasi shu. Obyektlar uchun yaxshi. Ammo massivlar uchun biz odatda qolgan elementlarning siljishini va bo’sh joyni egallashini istaymiz. Biz hozirda qisqaroq massivga ega bo’lishni kutmoqdamiz.

Shunday qilib, maxsus usullardan foydalanish kerak.

arr.splice(str) usuli – bu massivlar uchun “Shveytsariya armiyasining pichog’i”. U hamma narsani qilishi mumkin: elementlarni qo’shish, olib tashlash va kiritish.

Sintaksis:

arr.splice(start[, deleteCount, elem1, ..., elemN])

U indeks pozitsiyasidan boshlanadi: deleteCount elementlarini olib tashlaydi va keyin ularning o’rniga elem1, ..., elemN qo’shadi. O’chirilgan elementlar masssivini qaytaradi.

Ushbu usulni misollar yordamida tushunish oson.

O’chirish bilan boshlaymiz:

let arr = ["I", "study", "JavaScript"];

arr.splice(1, 1); // 1-indeksdan 1 ta elementni olib tashlang

alert( arr ); // ["I", "JavaScript"]

Oson, to‘g‘rimi? 1 indeksidan boshlab, u 1 elementni olib tashladi.

Keyingi misolda biz uchta elementni olib tashlaymiz va ularni qolgan ikkitasi bilan almashtiramiz:

let arr = ["I", "study", "JavaScript", "right", "now"];

// birinchi uchta elementni olib tashlang va ularni boshqasiga almashtiring
arr.splice(0, 3, "Let's", "dance");

alert( arr ) // hozir ["Let's", "dance", "right", "now"]

Bu erda splice o’chirilgan elementlar massivini qaytarishini ko’rishimiz mumkin:

let arr = ["I", "study", "JavaScript", "right", "now"];

// birinchi ikkita elementni olib tashlang
let removed = arr.splice(0, 2);

alert( removed ); // "I", "study" <-- o'chirilgan elementlarning massivi

splice usuli elementlarni hech qanday olib tashlamasdan kiritishga qodir. Buning uchun biz deleteCount ni 0 ga o’rnatishimiz kerak:

let arr = ["I", "study", "JavaScript"];

// indeks 2 dan
// o'chirish 0
// keyin "complex" va "language" ni kiriting
arr.splice(2, 0, "complex", "language");

alert(arr); // "I", "study", "complex", "language", "JavaScript"
Salbiy indekslarga ruxsat berilgan

Bu yerda va boshqa massiv usullarida salbiy indekslarga yo’l qo’yiladi. Ular massiv oxiridan pozitsiyani quyidagicha ko’rsatadilar:

let arr = [1, 2, 5];

// from index -1 (oxiridan bir qadam)
// 0 elementni o'chirish,
// keyin 3 va 4 ni kiriting
arr.splice(-1, 0, 3, 4);

alert( arr ); // 1,2,3,4,5

slice

arr.slice usuli o’xshash arr.splice ga qaraganda ancha sodda.

Sintaksis:

arr.slice([start], [end]);

U "start" dan "end" gacha ("end" hisobga olinmagan) barcha elementlarni o’z ichiga olgan yangi massivni qaytaradi. Har ikkala start va end ham salbiy bo’lishi mumkin, bu holda massiv oxiridan pozitsiya qabul qilinadi.

U str.slice kabi ishlaydi, lekin submatnlar o’rniga submassivlar yaratadi.

Masalan:

let arr = ["t", "e", "s", "t"];

alert(arr.slice(1, 3)); // e,s (copy from 1 to 3)

alert(arr.slice(-2)); // s,t (copy from -2 till the end)

We can also call it without arguments: arr.slice() creates a copy of arr. That’s often used to obtain a copy for further transformations that should not affect the original array.

concat

Metod arr.concat massivni boshqa massivlar va/yoki elementlar bilan birlashtiradi.

Sintaksis:

arr.concat(arg1, arg2...)

U har qanday argumentlarni qabul qiladi – yoki massivlar, yoki qiymatlar.

Natijada arr, keyin arg1, arg2 va hokazolarni o’z ichiga olgan yangi massiv hosil bo’ladi.

Agar argument massiv bo’lsa yoki Symbol.isConcatSpreadable xususiyatiga ega bo’lsa, unda uning barcha elementlari ko’chiriladi. Aks holda, argumentning o’zi ko’chiriladi.

Masalan:

let arr = [1, 2];

// arr ni [3,4] bilan birlashtirish
alert(arr.concat([3, 4])); // 1,2,3,4

// arr ni [3,4] va [5,6] bilan birlashtirish
alert(arr.concat([3, 4], [5, 6])); // 1,2,3,4,5,6

// arr ni [3,4] bilan birlashtirish, so'ngra 5 va 6 qiymatlarini qo'shish
alert(arr.concat([3, 4], 5, 6)); // 1,2,3,4,5,6

Odatda, u faqat elementlarni massivlardan ko’chiradi (ularni “tarqatadi”). Boshqa obyektlar, hatto ular massivga o’xshash bo’lsa ham, umuman qo’shiladi:

let arr = [1, 2];

let arrayLike = {
  0: "something",
  length: 1,
};

alert(arr.concat(arrayLike)); // 1,2,[object Object]

…Agar massivga o’xshash obyektda Symbol.isConcatSpreadable xususiyati bo’lsa, uning o’rniga uning elementlari qo’shiladi:

let arr = [1, 2];

let arrayLike = {
  0: "something",
  1: "else",
  [Symbol.isConcatSpreadable]: true,
  length: 2
};

alert( arr.concat(arrayLike) ); // 1,2,something,else

Takrorlash: forEach

arr.forEach usuli massivning har bir elementi uchun funktsiyani bajarishga imkon beradi.

Sintaksis:

arr.forEach(function (item, index, array) {
  // ... item bilan biror narsa qilish
});

Masalan, bu massivning har bir elementini ko’rsatadi:

// har bir element uchun ogohlantirish
["Bilbo", "Gandalf", "Nazgul"].forEach(alert);

Va ushbu kod maqsadli massivda ularning pozitsiyalari haqida batafsilroq ma’lumot berilgan:

["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
  alert(`${item} ${array} massivida ${index} indeksida`);
});

Funktsiya natijasi (agar u biron bir narsani qaytarsa) tashlanadi va e’tiborga olinmaydi.

Massivda qidirish

Bu massivda biror narsani qidirish usullari.

indexOf/lastIndexOf va includes

arr.indexOf, arr.lastIndexOf va arr.includes usullari bir xil sintaksisga ega. va aslida ularning matnga o’xshashadi, lekin belgilar o’rniga elementlarda ishlashadi:

  • arr.indexOf(item, from) from indeksdan boshlab item ni qidiradi va topilgan joyning indeksini qaytaradi, aks holda -1.
  • arr.lastIndexOf(item, from) – xuddi shunday, lekin o’ngdan chapga qidiradi.
  • arr.includes(item, from)from indeksdan boshlab item ni izlaydi, agar topilsa true qiymatini beradi.

Masalan:

let arr = [1, 0, false];

alert(arr.indexOf(0)); // 1
alert(arr.indexOf(false)); // 2
alert(arr.indexOf(null)); // -1

alert(arr.includes(1)); // true

E’tibor bering, usullarda === taqqoslash qo’llaniladi. Shunday qilib, agar biz false ni qidirsak, u nolni emas, balki false ni topadi.

Agar biz inklyuziyani tekshirishni istasak va aniq indeksni bilmoqchi bo’lmasak, u holda arr.includes afzal.

Bundan tashqari, include ning juda oz farqi shundaki, u indexOf/lastIndexOf dan farqli o’laroq, NaN da to’g’ri ishlaydi.

const arr = [NaN];
alert(arr.indexOf(NaN)); // -1 (0 bo'lishi kerak, lekin === tenglik NaN uchun ishlamaydi)
alert(arr.includes(NaN)); // true (to'g'ri)

find va findIndex

Bizda bir obyektlar massivi mavjudligini tasavvur qiling. Muayyan shartli obyektni qanday topishimiz mumkin?

Bu yerda arr.find usuli foydalidir.

Sintaksis:

let result = arr.find(function (item, index, array) {
  // agar true qaytarilsa, element qaytariladi va takrorlash to'xtatiladi
  // false senariy uchun undefined qaytariladi
});

Funktsiya massivning har bir elementi uchun takroriy ravishda chaqiriladi:

  • item element hisoblanadi.
  • index bu uning indeksidir.
  • array massivning o’zi.

Agar u true ni qaytarsa, qidiruv to’xtatiladi, item qaytariladi. Hech narsa topilmasa, undefined qaytariladi.

Masalan, bizda foydalanuvchilar massivi bor, ularning har biri id va name argumentlariga ega. Keling, id == 1 bilan topamiz:

let users = [
  { id: 1, name: "John" },
  { id: 2, name: "Pete" },
  { id: 3, name: "Mary" },
];

let user = users.find((item) => item.id == 1);

alert(user.name); // John

Haqiqiy hayotda obyektlar massivi odatiy holdir, shuning uchun find usuli juda foydali.

E’tibor bering, biz misolda item => item.id == 1 funktsiyasini bitta argument bilan topish ni ta’minlaymiz. Ushbu funktsiyaning boshqa argumentlari kamdan kam qo’llaniladi.

arr.findIndex usuli asosan bir xil, ammo u elementning o’zi o’rniga element topilgan indeksni qaytaradi va hech narsa topilmaganda -1 qaytariladi.

filter

find usuli funktsiyani true qaytaradigan yagona (birinchi) elementni qidiradi.

Agar ko’p bo’lsa, biz arr.filter(fn) dan foydalanishimiz mumkin.

Sintaksis find ga o’xshaydi, lekin true allaqachon qaytarilgan bo’lsa ham, massivning barcha elementlari uchun filtr takrorlashni davom ettiradi:

let results = arr.filter(function (item, index, array) {
  // agar true element natijalarga chiqarilsa va takrorlanish davom etsa
  // false senariy uchun bo'sh qatorni qaytaradi
});

Masalan:

let users = [
  { id: 1, name: "John" },
  { id: 2, name: "Pete" },
  { id: 3, name: "Mary" },
];

// dastlabki ikkita foydalanuvchi massivini qaytaradi
let someUsers = users.filter((item) => item.id < 3);

alert(someUsers.length); // 2

Massivni o’zgartirish

Ushbu bo’lim massivni o’zgartirish yoki qayta tartiblash usullari haqida.

map

arr.map usuli eng foydali va tez-tez ishlatiladigan usullardan biridir.

Sintaksis:

let result = arr.map(function (item, index, array) {
  // element o'rniga yangi qiymatni qaytaradi
});

U massivning har bir elementi uchun funktsiyani chaqiradi va natijalar massivini qaytaradi.

Masalan, biz har bir elementni uning uzunligiga aylantiramiz:

let lengths = ["Bilbo", "Gandalf", "Nazgul"].map((item) => item.length);
alert(lengths); // 5,7,6

sort(fn)

arr.sort usuli massivni joyida tartiblaydi.

Masalan:

let arr = [1, 2, 15];

// usul arr tarkibini qayta tartibga soladi (va uni qaytaradi)
arr.sort();

alert(arr); // 1, 15, 2

Natijada qandaydir g’alati narsani sezdingizmi?

Tartib 1, 15, 2 bo’ldi. Noto’g’ri. Lekin nega?

Sukut bo’yicha elementlar matn sifatida tartiblangan.

To’g’ridan-to’g’ri, barcha elementlar matnlarga aylantiriladi va keyin taqqoslanadi. Shunday qilib, leksikografik tartib qo’llaniladi va haqiqatan ham "2" > "15".

O’zimizning tartiblash usulimizdan foydalanish uchun biz ikkita argumentning funktsiyasini array.sort() argumenti sifatida ta’minlashimiz kerak.

Funktsiya shunday ishlashi kerak:

function compare(a, b) {
  if (a > b) return 1; // if the first value is greater than the second
  if (a == b) return 0; // if values are equal
  if (a < b) return -1; // if the first value is less than the second
}

Masalan:

function compareNumeric(a, b) {
  if (a > b) return 1;
  if (a == b) return 0;
  if (a < b) return -1;
}

let arr = [ 1, 2, 15 ];

arr.sort(compareNumeric);

alert(arr);  // 1, 2, 15

Endi u maqsadga muvofiq ishlaydi.

Keling, chetga chiqib, nima bo’layotganini o’ylab ko’raylik. arr har qanday narsaning massivi bo’lishi mumkin, shunday emasmi? Unda raqamlar yoki matnlar yoki HTML elementlari yoki boshqa narsalar bo’lishi mumkin. Bizda bir narsa to’plami mavjud. Uni saralash uchun uning elementlarini taqqoslashni biladigan tartiblash funktsiyasi kerak. Sukut bo’yicha matn tartibi.

arr.sort(fn) usuli tartiblash algoritmini o’rnatilgan dasturiga ega. Biz uning qanday ishlashiga ahamiyat berishimiz shart emas (ko’pincha optimallashtirilgan quicksort). U massivda yuradi, taqdim etilgan funktsiya yordamida elementlarini taqqoslaydi va ularni tartibini o’zgartiradi, bizga taqqoslashni amalga oshiradigan fn kerak bo’ladi.

Aytgancha, qaysi elementlar taqqoslanganligini bilmoqchi bo’lsak – ularni ogohlantirishga hech narsa to’sqinlik qilmaydi:

[1, -2, 15, 2, 0, 8].sort(function (a, b) {
  alert(a + " <> " + b);
  return a - b;
});

Algoritm bu jarayonda elementni bir necha marta taqqoslashi mumkin, ammo iloji boricha kamroq taqqoslashga harakat qiladi.

Taqqoslash funktsiyasi istalgan raqamni qaytarishi mumkin

Aslida, taqqoslash funktsiyasi faqat ijobiy sonni “kattaroq”, manfiy raqamni “kamroq” deb qaytarish uchun talab qilinadi.

Bu qisqa funktsiyalarni yozishga imkon beradi:

let arr = [ 1, 2, 15 ];

arr.sort(function(a, b) { return a - b; });

alert(arr);  // 1, 2, 15
O’q funktsiyalari eng yaxshisi

Esingizdami "function-expressions-arrows" maqolasi topilmadi? Biz ularni bu yerda chiroyli tartiblash uchun ishlatishimiz mumkin:

arr.sort( (a, b) => a - b );

Bu yuqoridagi boshqa, uzoqroq versiya bilan bir xil ishlaydi.

reverse

arr.reverse usuli arr dagi elementlarning tartibini o’zgartiradi.

Masalan:

let arr = [1, 2, 3, 4, 5];
arr.reverse();

alert(arr); // 5,4,3,2,1

Bu, shuningdek, arr massivni qaytaradi.

split va join

Mana, hayotdagi holat. Biz xabar almashish dasturini yozmoqdamiz va odam qabul qiluvchilarning vergul bilan ajratilgan ro’yxatini kiritdi: John, Pete, Mary. Ammo biz uchun ismlar massivi bitta matnga qaraganda ancha qulayroq bo’lar edi. Qanday qilib olish mumkin?

str.split(delim) usuli aynan shu narsani qiladi. U matnni berilgan massivga ajratadi delim.

Quyidagi misolda biz vergul bilan bo’sh joyni bo’ldik:

let names = "Bilbo, Gandalf, Nazgul";

let arr = names.split(", ");

for (let name of arr) {
  alert(`A message to ${name}.`); // A message to Bilbo  (va boshqa ismlar)
}

split usuli ixtiyoriy ikkinchi raqamli argumentga ega – bu massiv uzunligining chegarasi. Agar u taqdim etilsa, unda qo’shimcha elementlar e’tiborga olinmaydi. Amalda u kamdan-kam hollarda qo’llaniladi:

let arr = "Bilbo, Gandalf, Nazgul, Saruman".split(", ", 2);

alert(arr); // Bilbo, Gandalf
Harflarga bo’lish

Bo’sh s bilan split(s) ni chaqirish matnni harflar massiviga ajratadi:

let str = "test";

alert( str.split('') ); // t,e,s,t

arr.join(separator) chaqiruvi split ga teskari harakat qiladi. U orasida separator bilan yopishtirilgan arr matnini yaratadi.

Masalan:

let arr = ["Bilbo", "Gandalf", "Nazgul"];

let str = arr.join(";"); // glue the array into a string using ;

alert(str); // Bilbo;Gandalf;Nazgul

reduce/reduceRight

Biz massivni takrorlashimiz kerak bo’lganda – forEach, for yoki for..of dan foydalanishimiz mumkin.

Har bir element uchun ma’lumotlarni takrorlash va qaytarish kerak bo’lganda biz map dan foydalanishimiz mumkin.

arr.reduce va arr.reduceRight usullari ham ushbu zotga tegishli, ammo biroz murakkabroq. Ular massiv asosida bitta qiymatni hisoblash uchun ishlatiladi.

Sintaksis:

let value = arr.reduce(
  function (accumulator, item, index, array) {
    // ...
  },
  [initial]
);

Funktsiya elementlarga qo’llaniladi. Siz 2-dan boshlab tanish bo’lgan argumentlarni ko’rishingiz mumkin:

  • item – joriy massiv elementi.
  • index – uning pozitsiyasi.
  • array – bu massiv.

Hozircha, forEach/map kabi. Ammo yana bir argument bor:

  • previousValue – oldingi funktsiya chaqiruvining natijasidir, birinchi chaqiruv uchun boshlang'ich.

Buni tushunishning eng oson usuli, bu misol.

Bu erda biz bitta satrda massiv yig’indisini olamiz:

let arr = [1, 2, 3, 4, 5];

let result = arr.reduce((sum, current) => sum + current, 0);

alert(result); // 15

Bu erda biz faqat 2 ta argumentdan foydalanadigan reduce ning eng keng tarqalgan variantini qo’lladik.

Keling, nima bo’layotganini batafsil ko’rib chiqamiz.

  1. Birinchi bajarilishda sum – boshlang’ich qiymat (reduce ning so’nggi argumenti), 0 ga teng, va joriy qiymat – bu birinchi massiv elementi, 1 ga teng. Shunday qilib natija 1 dir.
  2. Ikkinchi bajarilishda sum = 1, unga ikkinchi massiv elementini (2) qo’shamiz va qaytaramiz.
  3. Uchinchi bajarilishda sum = 3 va unga yana bitta element qo’shamiz va hokazo…

Hisoblash oqimi:

Yoki jadval shaklida, bu yerda har bir satr keyingi qator elementidagi funktsiya chaqiruvini ifodalaydi:

sum current result
birinchi chaqiruv 0 1 1
ikkinchi chaqiruvl 1 2 3
uchinchi chaqiruv 3 3 6
to’rtinchi chaqiruv 6 4 10
beshinchi chaqiruv 10 5 15

Ko’rib turganimizdek, avvalgi qo’ng’iroq natijasi keyingisining birinchi argumentiga aylanadi.

Shuningdek, biz dastlabki qiymatni qoldirib yuborishimiz mumkin:

let arr = [1, 2, 3, 4, 5];

// reduce dan boshlang'ich qiymat o'chirildi (0 yo'q)
let result = arr.reduce((sum, current) => sum + current);

alert(result); // 15

Natija bir xil. Buning sababi shundaki, agar boshlang’ich bo’lmasa, unda reduce massivning birinchi elementini boshlang’ich qiymati sifatida qabul qiladi va takrorlashni 2-elementdan boshlaydi.

Hisoblash jadvali yuqoridagi kabi, birinchi qatorni olib tashlagach.

Ammo bunday foydalanish juda ehtiyotkorlik talab qiladi. Agar massiv bo’sh bo’lsa, u holda reduce chaqiruvi xatolikka olib keladi.

Mana bir misol:

let arr = [];

// Xato: boshlang'ich qiymati bo'lmagan bo'sh massivni kamaytirish
// agar boshlang'ich qiymat mavjud bo'lsa, reduce uni bo'sh arr uchun qaytaradi.
arr.reduce((sum, current) => sum + current);

Shuning uchun har doim boshlang’ich qiymatni ko’rsatish tavsiya etiladi.

arr.reduceRight usuli ham xuddi shunday qiladi, lekin o’ngdan chapga ishlaydi.

Array.isArray

Massivlar alohida til turini hosil qilmaydi. Ular obyektlarga asoslangan.

Shunday qilib, typeof oddiy obyektni massivdan ajratishga yordam bermaydi:

alert(typeof {}); // obyekt
alert(typeof []); // bir xil

…Ammo massivlar shu qadar tez-tez ishlatiladiki, buning uchun maxsus usul mavjud: Array.isArray(value). Agar value massiv bo’lsa, true, aks holda false ni qaytaradi.

alert(Array.isArray({})); // false

alert(Array.isArray([])); // true

Ko’p usullar “thisArg” ni qo’llab-quvvatlaydi

find, filter, map kabi funktsiyalarni chaqiradigan deyarli barcha massiv usullari, sort dan tashqari, thisArg qo’shimcha parametrlarini qabul qiladi.

Ushbu parametr yuqoridagi bo’limlarda tushuntirilmagan, chunki u kamdan kam qo’llaniladi. Ammo to’liqlik uchun biz buni qoplashimiz kerak.

Mana ushbu usullarning to’liq sintaksisi:

arr.find(func, thisArg);
arr.filter(func, thisArg);
arr.map(func, thisArg);
// ...
// thisArg ixtiyoriy oxirgi argument

thisArg parametrining qiymati func uchun this ga aylanadi.

Masalan, bu erda biz filtr sifatida obyekt usulidan foydalanamiz va thisArg foydalidir:

let army = {
  minAge: 18,
  maxAge: 27,
  canJoin(user) {
    return user.age >= this.minAge && user.age < this.maxAge;
  }
};

let users = [
  {age: 16},
  {age: 20},
  {age: 23},
  {age: 30}
];

// barcha user userdan yoshroq deb toping
let youngerUsers = users.filter(user.younger, user);

alert(soldiers.length); // 2
alert(soldiers[0].age); // 20
alert(soldiers[1].age); // 23

Yuqoridagi qo’ng’iroqda biz user.younger dan filtr sifatida foydalanamiz va buning uchun kontekst sifatida user ni taqdim etamiz. Agar biz kontekstni taqdim qilmagan bo’lsak, users.filter(user.younger) user.younger ni mustaqil funktsiya sifatida this = undefined bilan chaqiradi. Bu darhol xato degani.

Xulosa

Massiv usullaridan qo’llanma:

  • Elementlarni qo’shish/olib tashlash uchun:

    • push(...items) – oxiriga elementlarni qo’shadi,
    • pop() – elementni oxiridan ajratib oladi,
    • shift() – boshidan elementni ajratib oladi,
    • unshift(...items) – elementlarni boshiga qo’shadi.
    • splice(pos, deleteCount, ...items)pos indeksda deleteCount elementlarni o’chirish va items ni qo’shish.
    • slice(start, end) – yangi massiv yaratadi, elementlarni start dan end gacha (shu jumladan emas) massivga ko’chiradi.
    • concat(...items) – yangi massivni qaytaradi: mavjud bo’lgan barcha a’zolarni nusxalaydi va unga items larni qo’shadi. Agar items ning birortasi massiv bo’lsa, unda uning elementlari olinadi.
  • Elementlar orasida qidirish uchun:

    • indexOf/lastIndexOf(item, pos)pos holatidan boshlab item ni qidiradi, va indeksni qaytaradi, topilmasa -1 ni.
    • includes(value) – agar massivda value bo’lsa true, aks holda false qaytariladi.
    • find/filter(func) – funktsiya orqali elementlar filtrlaniladi, true qaytaradigan barcha qiymatlarni qaytaradi.
    • findIndex find ga o’xshaydi, lekin qiymat o’rniga indeksni qaytaradi.
  • Elementlar ustida takrorlash uchun:

    • forEach(func) – har bir element uchun func ni chaqiradi, hech narsa qaytarmaydi.
  • Massivni o’zgartirish uchun:

    • map(func) – har bir element uchun func ni chaqirish natijalaridan yangi massiv yaratadi.
    • sort(func) – massivni joyida saralaydi, keyin qaytaradi.
    • reverse() – massivni teskariga o’zgartiradi, keyin qaytaradi.
    • split/join – matnni massivga va orqaga aylantiradi.
    • reduce(func, initial) – har bir element uchun func chaqirib, chaqiruvlar orasidagi oraliq natijani berib, massiv ustida bitta qiymatni hisoblaydi.
  • Qo’shimcha:

    • Array.isArray(arr) arr massiv ekanligini tekshiradi.

Iltimos e’tibor bering, sort, reverse va splice usullari massivni o’zini o’zgartiradi.

Ushbu usullar eng ko’p ishlatiladigan usullar bo’lib, ular 99% holatlarni qamrab oladi. Ammo boshqalar ham bor:

  • arr.some(fn)/arr.every(fn) massivni tekshiradi.

    fn funktsiyasi massivning har bir elementida map ga o’xshash chaqiriladi. Agar natijala/natijalar true bo’lsa, true, aks holda false ni qaytaradi.

  • arr.fill(value, start, end) – qatorni start dan end gacha takrorlanadigan value bilan to’ldiradi.

  • arr.copyWithin(target, start, end) – uning elementlarini start pozitsiyasidan end pozitsiyasiga o’ziga, target pozitsiyasida nusxalash (mavjudligini qayta yozish).

To’liq ro’yxat uchun qo’llanma ga qarang…

Birinchi qarashdan juda ko’p usullar borligi esga olinishi qiyin tuyulishi mumkin. Ammo aslida bu ko’rinadiganidan ancha osonroq.

Ulardan xabardor bo’lish uchun qo’llanmani ko’rib chiqing. Keyin ushbu bobning vazifalarini amaliy ravishda hal qiling, shunda siz massiv usullari bilan tajribangizga ega bo’lasiz.

Keyinchalik, qachondir siz massiv bilan biror narsa qilishingiz kerak bo’lsa va qanday qilishni bilmasangiz – bu yerga keling, qo’llanmaga qarang va to’g’ri usulni toping. Uni to’g’ri yozishga misollar yordam beradi. Yaqinda siz usullarni avtomatik ravishda eslab qolasiz.

Vazifalar

“my-short-string” singari chiziqcha bilan ajratilgan so’zlarni tuya registr “myShortString” ga o’zgartiradigan camelize(str) funktsiyasini yozing.

Ya’ni: barcha chiziqlarni olib tashlaydi, chiziqdan keyingi har bir so’z tepa registr harfga aylanadi.

Masalan:

camelize("background-color") == "backgroundColor";
camelize("list-style-image") == "listStyleImage";
camelize("-webkit-transition") == "WebkitTransition";

P.S. Maslahat: matnni massivga bo’lish, uni o’zgartirish uchun split dan foydalaning va qo’shilish uchun join.

Sinovlar bilan sandbox-ni oching.

function camelize(str) {
  return str
    .split("-") // 'my-long-word' ni ['my', 'long', 'word'] massivga bo'ladi
    .map(
      // birinchisidan tashqari barcha massiv elementlarining birinchi harfini katta qiladi
      // ['my', 'long', 'word'] ni ['my', 'Long', 'Word'] ga aylantiradi
      (word, index) =>
        index == 0 ? word : word[0].toUpperCase() + word.slice(1)
    )
    .join(""); // ['my', 'Long', 'Word'] ni 'myLongWord' ga birlashtiradi
}

Yechimni sandbox-dagi sinovlar bilan oching.

arr massivini oladigan, undagi a va b orasidagi elementlarni qidiradigan va ularning massivini qaytaradigan filterRange(arr,a,b) funktsiyasini yozing.

Funktsiya massivni o’zgartirmasligi kerak. Bu yangi massivni qaytarishi kerak.

Masalan:

let arr = [5, 3, 8, 1];

let filtered = filterRange(arr, 1, 4);

alert(filtered); // 3,1 (mos keladigan qiymatlar)

alert(arr); // 5,3,8,1 (o'zgartirilmagan)

Sinovlar bilan sandbox-ni oching.

function filterRange(arr, a, b) {
  // yaxshi o'qilishi uchun ifoda atrofiga qavslar qo'shildi
  return arr.filter((item) => a <= item && item <= b);
}

let arr = [5, 3, 8, 1];

let filtered = filterRange(arr, 1, 4);

alert(filtered); // 3,1 (mos keladigan qiymatlar)

alert(arr); // 5,3,8,1 (o'zgartirilmagan)

Yechimni sandbox-dagi sinovlar bilan oching.

arr massivini oladigan va undan a va b gacha bo’lgan qiymatlardan tashqari barcha qiymatlarni olib tashlaydigan filterRangeInPlace(arr,a,b) funktsiyasini yozing. Sinov: a ≤ arr[i] ≤ b.

Funktsiya faqat massivni o’zgartirishi kerak. Hech narsa qaytarmasligi kerak.

Masalan:

let arr = [5, 3, 8, 1];

filterRangeInPlace(arr, 1, 4); // 1 dan 4 gacha raqamalrdan tashqari raqamlarni chiqarib tashladi

alert(arr); // [3, 1]

Sinovlar bilan sandbox-ni oching.

function filterRangeInPlace(arr, a, b) {
  for (let i = 0; i < arr.length; i++) {
    let val = arr[i];

    // intervaldan tashqarida bo'lsa olib tashlang
    if (val < a || val > b) {
      arr.splice(i, 1);
      i--;
    }
  }
}

let arr = [5, 3, 8, 1];

filterRangeInPlace(arr, 1, 4); // 1 dan 4 gacha raqamalrdan tashqari raqamlarni chiqarib tashladi

alert(arr); // [3, 1]

Yechimni sandbox-dagi sinovlar bilan oching.

let arr = [5, 2, 1, -10, 8];

// ... uni teskari tartibda saralash uchun sizning kodingiz

alert(arr); // 8, 5, 2, 1, -10
let arr = [5, 2, 1, -10, 8];

arr.sort((a, b) => b - a);

alert(arr);

Bizda arr massivi mavjud. Biz uning tartiblangan nusxasini olishni xohlaymiz, ammo arr ni o’zgartirmasdan.

Bunday nusxani qaytaradigan copySorted(arr) funktsiyasini yarating.

let arr = ["HTML", "JavaScript", "CSS"];

let sorted = copySorted(arr);

alert(sorted); // CSS, HTML, JavaScript
alert(arr); // HTML, JavaScript, CSS (hech qanday o'zgarish yo'q)

Nusxasini olish va undagi tartibni bajarish uchun slice() dan foydalanishimiz mumkin:

function copySorted(arr) {
  return arr.slice().sort();
}

let arr = ["HTML", "JavaScript", "CSS"];

let sorted = copySorted(arr);

alert( sorted );
alert( arr );

“Kengaytiriladigan” kalkulyator obyektlarini yaratadigan Calculator konstruktor funktsiyasini yarating.

Vazifa ikki qismdan iborat.

  1. Birinchidan, “NUMBER operatori NUMBER” (bo’shliq bilan ajratilgan) formatida "1 + 2" kabi matni qabul qiladigan va natijani qaytaradigan calculate(str) usulini qo’llang. Plyus + va minus - ni tushunishi kerak.

    Foydalanish misoli:

    let calc = new Calculator();
    
    alert(calc.calculate("3 + 7")); // 10
  2. Keyin kalkulyatorga yangi operatsiyani o’rgatadigan addMethod(name, func) usulini qo’shing. Buning uchun name operatori va uni amalga oshiradigan ikkita argumentli funktsiya func(a, b) kerak bo’ladi.

    Masalan, ko’paytma *, bo’linma / va darajani ** qo’shamiz:

    let powerCalc = new Calculator();
    powerCalc.addMethod("*", (a, b) => a * b);
    powerCalc.addMethod("/", (a, b) => a / b);
    powerCalc.addMethod("**", (a, b) => a ** b);
    
    let result = powerCalc.calculate("2 ** 3");
    alert(result); // 8
  • Ushbu topshiriqda qavs yoki murakkab ifodalar yo’q.
  • Raqamlar va operator to’liq bitta bo’sh joy bilan chegaralangan.
  • Agar uni qo’shmoqchi bo’lsangiz, ishlov berishda xato bo’lishi mumkin.

Sinovlar bilan sandbox-ni oching.

  • Iltimos, usullarning qanday saqlanishiga e’tibor bering. Ular oddiygina ichki ob’ektga qo’shiladi.
  • Barcha testlar va raqamli konvertatsiyalar hisoblash usulida amalga oshiriladi. Kelajakda u yanada murakkab iboralarni qo’llab-quvvatlash uchun kengaytirilishi mumkin.
function Calculator() {
  this.methods = {
    "-": (a, b) => a - b,
    "+": (a, b) => a + b,
  };

  this.calculate = function (str) {
    let split = str.split(" "),
      a = +split[0],
      op = split[1],
      b = +split[2];

    if (!this.methods[op] || isNaN(a) || isNaN(b)) {
      return NaN;
    }

    return this.methods[op](a, b);
  };

  this.addMethod = function (name, func) {
    this.methods[name] = func;
  };
}

Yechimni sandbox-dagi sinovlar bilan oching.

Sizda user obyektlari massivi mavjud, ularning har biri user.name ega. Uni nomlar massiviga o’zgartiradigan kodni yozing.

Masalan:

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };

let users = [john, pete, mary];

let names =
  /* ... sizning kodingiz */

  alert(names); // John, Pete, Mary
let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };

let users = [john, pete, mary];

let names = users.map((item) => item.name);

alert(names); // John, Pete, Mary

Sizda user obyekyektlar massivi mavjud, ularning har birida ism, familiya va id mavjud.

Undan id va fullName obyektlarining boshqa massivni yaratish uchun kodni yozing, bu yerda to'liq ism ism va familiya dan hosil bo’ladi.

Masalan:

let john = { name: "John", surname: "Smith", id: 1 };
let pete = { name: "Pete", surname: "Hunt", id: 2 };
let mary = { name: "Mary", surname: "Key", id: 3 };

let users = [ john, pete, mary ];

let usersMapped = /* ... sizning kodingiz ... */

/*
usersMapped = [
  { fullName: "John Smith", id: 1 },
  { fullName: "Pete Hunt", id: 2 },
  { fullName: "Mary Key", id: 3 }
]
*/

alert( usersMapped[0].id ) // 1
alert( usersMapped[0].fullName ) // John Smith

Shunday qilib, aslida siz bir obyektlar massivini boshqasiga solishtirishingiz kerak. Bu erda => dan foydalanib ko’ring.

let john = { name: "John", surname: "Smith", id: 1 };
let pete = { name: "Pete", surname: "Hunt", id: 2 };
let mary = { name: "Mary", surname: "Key", id: 3 };

let users = [ john, pete, mary ];

let usersMapped = users.map(user => ({
  fullName: `${user.name} ${user.surname}`,
  id: user.id
}));

/*
usersMapped = [
  { fullName: "John Smith", id: 1 },
  { fullName: "Pete Hunt", id: 2 },
  { fullName: "Mary Key", id: 3 }
]
*/

alert( usersMapped[0].id ); // 1
alert( usersMapped[0].fullName ); // John Smith

Iltimos, o’q funktsiyalari uchun biz qo’shimcha qavslardan foydalanishimiz kerakligini unutmang.

Biz bunday yozolmaymiz:

let usersMapped = users.map(user => {
  fullName: `${user.name} ${user.surname}`,
  id: user.id
});

Yodimizda bo’lganidek, ikkita o’q funktsiyasi mavjud: tanasiz value => expr va tanali value => {...}.

Bu erda JavaScript { ni obyektning boshlanishi emas, balki funktsiya tanasining boshlanishi sifatida qabul qiladi. Vaqtinchalik yechim ularni “oddiy” qavslarga o’rashdan iborat:

let usersMapped = users.map(user => ({
  fullName: `${user.name} ${user.surname}`,
  id: user.id
}));

Endi yaxshi.

age xususiyatiga ega bo’lgan bir obyektlarning massivini oladigan va ularni yoshi bo’yicha saralaydigan sortByAge(users) funktsiyasini yozing.

Masalan:

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };

let arr = [pete, john, mary];

sortByAge(arr);

// hozir: [john, mary, pete]
alert(arr[0].name); // John
alert(arr[1].name); // Mary
alert(arr[2].name); // Pete
function sortByAge(arr) {
  arr.sort((a, b) => a.age - b.age);
}

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };

let arr = [pete, john, mary];

sortByAge(arr);

// endi tartiblangan: [john, mary, pete]
alert(arr[0].name); // John
alert(arr[1].name); // Mary
alert(arr[2].name); // Pete

Massiv elementlarini aralashtiruvchi (tasodifiy tartiblash) shuffle(array) funktsiyasini yozing.

Bir necha marta aralashtirish elementlarning turli xil tartiblariga olib kelishi mumkin. Misol uchun:

let arr = [1, 2, 3];

shuffle(arr);
// arr = [3, 2, 1]

shuffle(arr);
// arr = [2, 1, 3]

shuffle(arr);
// arr = [3, 1, 2]
// ...

Barcha element chaqiruvlari teng ehtimolga ega bo’lishi kerak. Masalan, [1,2,3] teng ehtimollik bilan [1,2,3] yoki [1,3,2] yoki [3,1,2] va boshqalar sifatida o’zgartirilishi mumkin.

Oddiy yechim bo’lishi mumkin:

function shuffle(array) {
  array.sort(() => Math.random() - 0.5);
}

let arr = [1, 2, 3];
shuffle(arr);
alert(arr);

Bu biroz ishlaydi, chunki Math.random() - 0.5 tasodifiy son bo’lib, u ijobiy yoki salbiy bo’lishi mumkin, shuning uchun saralash funktsiyasi elementlarni tasodifiy tartibda o’zgartiradi.

Ammo saralash funktsiyasi shu tarzda ishlatilishi mumkin emasligi sababli, barcha almashtirishlar bir xil ehtimollikka ega emas.

Masalan, quyidagi kodni ko’rib chiqing. U aralashtirib 1000000 marta ishlaydi va barcha mumkin bo’lgan natijalarning ko’rinishini hisoblaydi:

function shuffle(array) {
  array.sort(() => Math.random() - 0.5);
}

// barcha mumkin bo'lgan almashtirishlar uchun ko'rinishlarning soni
let count = {
  123: 0,
  132: 0,
  213: 0,
  231: 0,
  321: 0,
  312: 0,
};

for (let i = 0; i < 1000000; i++) {
  let array = [1, 2, 3];
  shuffle(array);
  count[array.join("")]++;
}

// barcha mumkin bo'lgan almashtirishlarning sonlarini ko'rsatish
for (let key in count) {
  alert(`${key}: ${count[key]}`);
}

Misol natijasi (for V8, July 2017):

123: 250706
132: 124425
213: 249618
231: 124880
312: 125148
321: 125223

Ikkilanishni aniq ko’rishimiz mumkin: 123 va 213 boshqalarga qaraganda tez-tez ko’rinadi.

Kod natijasi JavaScript interpretator o’rtasida farq qilishi mumkin, ammo biz allaqachon yondashuv ishonchsizligini ko’rmoqdamiz.

Nima uchun u ishlamayapti? Umuman aytganda, sort “qora quti” dir: biz unga qator va taqqoslash funktsiyasini tashlaymiz va massivning tartiblanishini kutamiz. Ammo taqqoslashning mutlaqo tasodifiyligi tufayli qora quti aqldan ozadi va uning aynan qay darajada aqldan ozishi interpretator orasidagi farqning aniq bajarilishiga bog’liq.

Vazifani bajarishning boshqa yaxshi usullari mavjud. Masalan, Fisher-Yates shuffle deb nomlangan ajoyib algoritm mavjud. Maqsad massivni teskari tartibda o’tkazosh va har bir elementni tasodifiy element bilan almashtirishdir:

function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1)); // 0 dan i gacha bo'lgan tasodifiy indeks
    [array[i], array[j]] = [array[j], array[i]]; // elementlarni almashtirish
  }
}

Keling, xuddi shu tarzda sinab ko’raylik:

function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
}

// barcha mumkin bo'lgan almashtirishlar uchun ko'rinishlarning soni
let count = {
  123: 0,
  132: 0,
  213: 0,
  231: 0,
  321: 0,
  312: 0,
};

for (let i = 0; i < 1000000; i++) {
  let array = [1, 2, 3];
  shuffle(array);
  count[array.join("")]++;
}

// barcha mumkin bo'lgan almashtirishlarning sonlarini ko'rsatish
for (let key in count) {
  alert(`${key}: ${count[key]}`);
}

Misol natijasi:

123: 166693
132: 166647
213: 166628
231: 167517
312: 166199
321: 166316

Hozir yaxshi ko’rinishga ega: barcha almashtirishlar bir xil ehtimollik bilan paydo bo’ladi.

Shuningdek, Fisher-Yates algoritmi ishlash samaradorligi jihatidan ancha yaxshi, ortiqcha “saralash” mavjud emas.

getAverageAge(users) funktsiyasini yozing, bu age xususiyatiga ega bo’lgan obyektlar massivini oladi va o’rtacha qiymatni qaytaradi.

O’rtacha son uchun formula (age1 + age2 + ... + ageN) / N.

Misol uchun:

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 29 };

let arr = [john, pete, mary];

alert(getAverageAge(arr)); // (25 + 30 + 29) / 3 = 28
function getAverageAge(users) {
  return users.reduce((prev, user) => prev + user.age, 0) / users.length;
}

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 29 };

let arr = [john, pete, mary];

alert(getAverageAge(arr)); // 28

Keling, arr massiv bo’lsin.

arr ning noyob elementlari bo’lgan massivni qaytarishi kerak bo’lgan unique(arr) funktsiyasini yarating.

Masalan:

function unique(arr) {
  /* sizning kodingiz */
}

let strings = [
  "Hare",
  "Krishna",
  "Hare",
  "Krishna",
  "Krishna",
  "Krishna",
  "Hare",
  "Hare",
  ":-O",
];

alert(unique(strings)); // Hare, Krishna, :-O

Sinovlar bilan sandbox-ni oching.

Keling, massiv elementlari bo’ylab yuraylik:

  • Har bir element uchun, natijada olingan massivda ushbu element mavjudligini tekshiramiz.
  • Agar shunday bo’lsa, unda e’tibor bermang, aks holda natijalarga qo’shing.
function unique(arr) {
  let result = [];

  for (let str of arr) {
    if (!result.includes(str)) {
      result.push(str);
    }
  }

  return result;
}

let strings = [
  "Hare",
  "Krishna",
  "Hare",
  "Krishna",
  "Krishna",
  "Krishna",
  "Hare",
  "Hare",
  ":-O",
];

alert(unique(strings)); // Hare, Krishna, :-O

Kod ishlaydi, lekin unda potentsial ishlash muammosi mavjud.

result.include(str) massivning ichida yuradi va result moslikni topish uchun har bir elementni str bilan taqqoslaydi.

Shunday qilib, agar natija da 100 element bo’lsa va hech kim str ​​ga to’g’ri kelmasa, u butun natija da yuradi va to’liq 100 taqqoslashni amalga oshiradi. Agar natija 10000 kabi katta bo’lsa, u holda 10000 taqqoslash bo’ladi.

Bu o’z-o’zidan muammo emas, chunki JavaScript-ni interpretatorlari juda tez, shuning uchun 10000 lik massivdan yurish mikrosaniyadagi masala.

Ammo biz arr ning har bir elementi uchun for tsiklida shunday test o’tkazamiz.

Shunday qilib, agar arr.length 10000 bo’lsa, bizda 10000 * 10000 = 100 million taqqoslash kabi narsa bo’ladi. Bu juda ko’p.

Shunday qilib, yechim faqat kichik massivlar uchun foydalidir.

Keyinchalik "map-set-weakmap-weakset" maqolasi topilmadi bobida biz uni qanday qilib optimallashtirishni ko’rib chiqamiz.

Yechimni sandbox-dagi sinovlar bilan oching.

Aytaylik, bizga {id:..., name:..., age... } shaklida foydalanuvchilar massivi keldi.

Undan obyekt yaratiladigan groupById(arr) funksiyasini yarating, bu yerda id kalit bo’lib, massiv elementlari qiymat bo’ladi.

Masalan:

let users = [
  { id: "john", name: "John Smith", age: 20 },
  { id: "ann", name: "Ann Smith", age: 24 },
  { id: "pete", name: "Pete Peterson", age: 31 },
];

let usersById = groupById(users);

/*
// chaqiruvdan keyin bizda bo'lishi kerak:

usersById = {
  john: {id: 'john', name: "John Smith", age: 20},
  ann: {id: 'ann', name: "Ann Smith", age: 24},
  pete: {id: 'pete', name: "Pete Peterson", age: 31},
}
*/

Bunday funksiya server ma’lumotlari bilan ishlashda juda qulay.

Bu vazifada biz id ning noyob ekanligini faraz qilamiz. Bir xil id ga ega ikkita massiv elementi bo’lmasligi mumkin.

Iltimos, yechimda massivning .reduce usulidan foydalaning.

Sinovlar bilan sandbox-ni oching.

function groupById(array) {
  return array.reduce((obj, value) => {
    obj[value.id] = value;
    return obj;
  }, {});
}

Yechimni sandbox-dagi sinovlar bilan oching.

O'quv qo'llanma xaritasi

Izohlar

izoh berishdan oldin buni o'qing…
  • Agar sizda nimani yaxshilash kerakligi haqida takliflaringiz bo'lsa - iltimos, GitHub muammosini yuboring yoki izoh berish o'rniga so'rov yuboring.
  • Agar siz maqolada biror narsani tushunolmasangiz - iltimos, batafsilroq ma'lumot bering.
  • Bir nechta so'z so'zlarini kiritish uchun <code> yorlig'ini ishlating, bir nechta satrlar uchun - ularni <pre> yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)