Go’da massiv va make funksiyasi
Massiv (array) bir xil turdagi va soni o‘zgarmaydigan elementlarni ketma-ket saqlaydi. Masalan, haftaning har bir
kunidagi harorat uchun doim yettita qiymat kerak. Bu qiymatlarni [7]float64 massivida saqlash mumkin.
Go’da massiv uzunligi uning turining bir qismi hisoblanadi. Shu sabab [3]int va [4]int boshqa-boshqa turlardir.
Massiv yaratilgandan keyin unga yangi element uchun joy qo‘shib yoki uning uzunligini qisqartirib bo‘lmaydi.
Massivni e’lon qilish
Massiv turi [uzunlik]elementTuri ko‘rinishida yoziladi:
package main
import "fmt"
func main() {
var ballar [4]int
ballar[0] = 78
ballar[1] = 91
fmt.Println(ballar)
fmt.Println("Uzunligi:", len(ballar))
}
Natija:
var ballar [4]int qatori to‘rtta int qiymati uchun joy ajratadi. Qiymat berilmagan elementlar dastlab 0 bo‘ladi.
Chunki 0 — int turining nol qiymati. Nol qiymat o‘zgaruvchi yaratilganda Go avtomatik beradigan boshlang‘ich
qiymatdir.
Massivdagi har bir element indeks, ya’ni uning tartib raqami orqali tanlanadi. Indeks 0 dan boshlanadi. Demak,
to‘rtta elementli massivning indekslari 0, 1, 2 va 3 bo‘ladi. Misolda dastlabki ikkita elementga qiymat
berilgan. Qolgan ikkita element esa 0 bo‘lib qolgan.
Warning
ballar[4] deb yozib bo‘lmaydi, chunki bu massivda 4-indeks yo‘q. Chegaradan tashqaridagi indeks kodning
o‘zida aniq yozilsa, kompilyator xato beradi. Indeks dastur ishlayotgan paytda hisoblanib, chegaradan chiqib ketsa,
dastur panic bilan to‘xtaydi.
Massiv literalari
Qiymatlarni e’lon qilish paytida berish mumkin:
package main
import "fmt"
func main() {
ranglar := [3]string{"qizil", "yashil", "ko‘k"}
sonlar := [...]int{10, 20, 30, 40}
fmt.Println(ranglar)
fmt.Println(sonlar, len(sonlar))
}
Natija:
[3]string yozuvida massiv uzunligi aniq ko‘rsatilgan. [...]int ichidagi ... esa uzunlikni berilgan elementlar
sonidan aniqlashni kompilyatorga topshiradi. sonlar ichida to‘rtta element borligi uchun uning turi [4]int bo‘ladi.
Massiv bo‘ylab yurish
Massivning barcha elementlarini ketma-ket o‘qish uchun range ishlatiladi. U siklning har bir iteratsiyasida element
indeksi va qiymatini beradi. Iteratsiya — sikl tanasining bir marta bajarilishi.
package main
import "fmt"
func main() {
ballar := [4]int{78, 91, 85, 88}
yigindi := 0
for indeks, ball := range ballar {
fmt.Printf("%d-indeks: %d\n", indeks, ball)
yigindi += ball
}
fmt.Println("O‘rtacha:", float64(yigindi)/float64(len(ballar)))
}
Natija:
Sikl har bir ball qiymatini yigindi o‘zgaruvchisiga qo‘shadi. O‘rtacha qiymatni hisoblash uchun yig‘indi elementlar
soniga bo‘linadi. Bo‘lishdan oldin ikkala qiymat ham float64 turiga o‘tkazilgan. Aks holda Go ikkita int qiymatini
bo‘ladi va natijaning kasr qismini tashlab yuboradi.
Massivdan nusxa olish
Massivni boshqa o‘zgaruvchiga berganda Go uning barcha elementlaridan alohida nusxa oladi. Nusxadagi elementni o‘zgartirish dastlabki massivga ta’sir qilmaydi:
package main
import "fmt"
func main() {
asl := [3]int{1, 2, 3}
nusxa := asl
nusxa[0] = 99
fmt.Println("Asl:", asl)
fmt.Println("Nusxa:", nusxa)
}
Natija:
Misolda asl va nusxa bir xil qiymatlardan tuzilgan ikkita mustaqil massiv bo‘ldi. Shu sabab nusxa[0]
o‘zgartirilganda asl[0] avvalgi qiymatini saqlab qoldi.
Massiv funksiyaga argument sifatida uzatilganda ham to‘liq nusxalanadi. Argument — funksiyaga chaqirish paytida beriladigan qiymat. Katta massivni funksiyaga qayta-qayta uzatish ortiqcha nusxalar yaratishi mumkin. Bunday holatda ko‘pincha slice ishlatiladi.
Massivlarni taqqoslash
Bir xil turdagi ikkita massivni == va != operatorlari bilan taqqoslash mumkin. Go bir xil indeksda turgan
elementlarni ketma-ket solishtiradi. Barcha mos elementlar teng bo‘lsagina massivlar teng hisoblanadi.
Bu imkoniyat massiv elementining turiga ham bog‘liq. Masalan, int va string qiymatlarini taqqoslash mumkin.
Shuning uchun ulardan tuzilgan massivlar ham taqqoslanadi. Element turi taqqoslanmaydigan bo‘lsa, massivni ham ==
bilan tekshirib bo‘lmaydi.
make massiv uchun ishlatilmaydi
make Go’ga o‘rnatilgan funksiyalardan biridir. U slice, map va channel turlarini yaratib, ishlashga tayyorlaydi.
Slice — elementlar sonini o‘zgartirish mumkin bo‘lgan ketma-ketlik. map kalit va qiymat juftlarini saqlaydi, channel
esa goroutinlar orasida qiymat uzatishda ishlatiladi.
Massivga make kerak emas. Massiv e’lon qilinganda uning barcha elementlari uchun joy darhol ajratiladi.
Shuning uchun quyidagi kod kompilyatsiyadan o‘tmaydi:
Massivdan farqini ko‘rish uchun make yordamida slice yaratamiz. Bunda ikkinchi argument slice uzunligini, uchinchi
argument esa sig‘imini bildiradi. Sig‘im — slice asosidagi xotirada nechta element uchun joy borligini ko‘rsatuvchi
qiymat.
package main
import "fmt"
func main() {
sonlar := make([]int, 3, 5)
sonlar[0] = 10
fmt.Println(sonlar)
fmt.Println("Uzunlik:", len(sonlar), "Sig‘im:", cap(sonlar))
}
Natija:
make([]int, 3, 5) uzunligi 3, sig‘imi 5 bo‘lgan slice yaratadi. Uning hozir foydalanish mumkin bo‘lgan uchta
elementi bor. Bu elementlar dastlab 0 qiymatini oladi. Shu paytda faqat 0, 1 va 2 indekslariga murojaat qilish
mumkin.
Sig‘im 5 ekanligi sonlar[3] indeksi hoziroq mavjud degani emas. Avval slice uzunligini append() yordamida yoki
sig‘im chegarasida qayta kesish orqali oshirish kerak. Slice uzunligi va sig‘imi keyingi darsda batafsil tushuntiriladi.
Qachon massiv ishlatiladi?
Elementlar soni oldindan ma’lum va o‘zgarmas bo‘lsa, massivdan foydalanish qulay. Masalan, IPv4 manzili doim to‘rtta
baytdan iborat. Uni [4]byte turi bilan ifodalash mumkin. 32 baytli xesh qiymati uchun esa [32]byte mos keladi.
Elementlar soni dastur ishlashi davomida ko‘payishi yoki kamayishi mumkin bo‘lsa, odatda slice ishlatiladi. Demak, massiv va slice orasidagi tanlov avvalo elementlar soni o‘zgarishi yoki o‘zgarmasligiga bog‘liq.
Qo‘shimcha misollar
1. Uzunlikni kompilyatorga aniqlatish
package main
import "fmt"
func main() {
ranglar := [...]string{"qizil", "yashil", "ko‘k"}
fmt.Printf("%T, uzunligi: %d\n", ranglar, len(ranglar))
}
Natija:
... yozuvi massiv uzunligini qo‘lda kiritmaslik imkonini beradi. Kompilyator uchta rang borligini ko‘radi va
ranglar turini [3]string deb belgilaydi.
2. Indeksli massiv literali
Natija:
Massiv literalida faqat kerakli indekslarga qiymat berish ham mumkin. Bu misolda 1-indeksga 10, 4-indeksga
esa 40 yoziladi. Qolgan elementlar int turining nol qiymati — 0 bilan to‘ldiriladi.
3. Massivlarni tenglik bilan solishtirish
package main
import "fmt"
func main() {
a := [3]int{1, 2, 3}
b := [3]int{1, 2, 3}
fmt.Println(a == b)
}
Natija:
a va b bir xil [3]int turiga ega. Ularning mos indekslaridagi qiymatlar ham teng. Shu sabab dastur true
qiymatini ekranga chiqaradi.
4. Massiv nusxasini o‘zgartirish
package main
import "fmt"
func main() {
asl := [3]int{2, 4, 6}
nusxa := asl
for i := range nusxa {
nusxa[i] *= 2
}
fmt.Println("Asl:", asl)
fmt.Println("Nusxa:", nusxa)
}
Natija:
nusxa := asl barcha elementlardan nusxa oladi. Sikl faqat nusxa elementlarini ikki baravar oshiradi. Natijada
asl o‘z holicha qoladi.
5. Massiv yig‘indisini hisoblash
package main
import "fmt"
func main() {
sonlar := [5]int{4, 7, 2, 9, 3}
yigindi := 0
for _, son := range sonlar {
yigindi += son
}
fmt.Println(yigindi)
}
Natija:
range indeks va qiymat qaytaradi. Bu misolda indeks kerak emasligi uchun uning o‘rniga bo‘sh identifikator _
yozilgan. Har bir qiymat yigindiga qo‘shiladi va dastur 25 sonini ekranga chiqaradi.
6. Eng katta element indeksini topish
package main
import "fmt"
func main() {
sonlar := [5]int{4, 17, 8, 17, 3}
engKatta := 0
for i := 1; i < len(sonlar); i++ {
if sonlar[i] > sonlar[engKatta] {
engKatta = i
}
}
fmt.Println(engKatta, sonlar[engKatta])
}
Natija:
engKatta o‘zgaruvchisi qiymatni emas, eng katta element indeksini saqlaydi. Dastlab 0-indeksdagi element eng
katta deb olinadi. Sikl qolgan elementlarni sonlar[engKatta] qiymati bilan solishtiradi.
Taqqoslashda > ishlatilgan. Shu sabab eng katta qiymat bir necha marta uchrasa, uning birinchi indeksi saqlanadi.
Bu massivda 17 ikki marta uchraydi, lekin natijada uning birinchi indeksi — 1 chiqadi.
7. Ikki o‘lchamli massiv
package main
import "fmt"
func main() {
matritsa := [2][3]int{{1, 2, 3}, {4, 5, 6}}
for qator := range matritsa {
for ustun := range matritsa[qator] {
fmt.Print(matritsa[qator][ustun], " ")
}
fmt.Println()
}
}
Natija:
[2][3]int — ikki qatorli va uch ustunli massiv. Har bir qatorning o‘zi uchta elementdan iborat [3]int massivi
hisoblanadi. Elementni olish uchun avval qator, keyin ustun indeksi yoziladi: matritsa[qator][ustun].
8. Matritsaning bosh diagonali
package main
import "fmt"
func main() {
matritsa := [3][3]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
yigindi := 0
for i := range matritsa {
yigindi += matritsa[i][i]
}
fmt.Println(yigindi)
}
Natija:
Bosh diagonaldagi elementlarning qator va ustun indekslari bir xil bo‘ladi: [0][0], [1][1] va [2][2].
Sikl 1, 5 va 9 qiymatlarini qo‘shadi. Shu sabab natija 15 bo‘ladi.
9. Raqamlar chastotasi
package main
import "fmt"
func main() {
son := 120221
var sanoq [10]int
for son > 0 {
sanoq[son%10]++
son /= 10
}
fmt.Println(sanoq)
}
Natija:
Bu misolda massiv indeksi raqamning o‘zini bildiradi. Indeksdagi qiymat esa shu raqam necha marta uchraganini
saqlaydi. Masalan, sanoq[2] qiymati 2 raqamining son ichida necha marta borligini ko‘rsatadi. 120221 sonida
1 ikki marta, 2 esa uch marta qatnashgan.
O‘nlik sanoq tizimida 0 dan 9 gacha doim o‘nta raqam bor. Elementlar soni o‘zgarmagani uchun bu vazifada
[10]int massivi mos keladi.
Info
Ushbu sodda misolda son musbat deb olingan. Agar son qiymati aynan 0 bo‘lsa, sikl ishlamaydi va nol raqami
sanalmaydi. Tashqi ma’lumot bilan ishlaydigan dasturda bu holatni alohida tekshirish kerak.
10. Massivni joyida teskari qilish
package main
import "fmt"
func main() {
massiv := [5]int{10, 20, 30, 40, 50}
for chap, ong := 0, len(massiv)-1; chap < ong; chap, ong = chap+1, ong-1 {
massiv[chap], massiv[ong] = massiv[ong], massiv[chap]
}
fmt.Println(massiv)
}
Natija:
chap indeksi massiv boshidan, ong esa oxiridan yuradi. Har bir iteratsiyada shu indekslardagi qiymatlar o‘zaro
almashtiriladi. Indekslar uchrashganda sikl tugaydi. O‘zgartirish massivning o‘zida bajarilgani uchun qo‘shimcha massiv
kerak emas.
Keyingi darsda elementlar sonini o‘zgartirish mumkin bo‘lgan slice, uning uzunligi, sig‘imi va append() funksiyasi
bilan ishlashni o‘rganamiz.