10-bo‘lim
Maplar
Kalit-qiymat saqlash, comma-ok tekshiruvi, o'chirish, tartibning ataylab tasodifiyligi va uni saralab chiqarish usuli.
Ushbu bo‘lim mundarijasi
map - kalit bo'yicha qiymat saqlaydigan tur. Boshqa tillarda uni
lug'at, hash yoki assotsiativ massiv deb atashadi.
Yaratish va ishlatish #
package main
import "fmt"
func main() {
yoshlar := map[string]int{
"Husanboy": 25,
"Malika": 20,
"Nodira": 22,
}
fmt.Println(yoshlar["Malika"])
fmt.Println(len(yoshlar))
yoshlar["Aziza"] = 19
yoshlar["Malika"] = 21
fmt.Println(len(yoshlar), yoshlar["Malika"])
}
20
3
4 21
map[kalit]qiymat - kalit turi kvadrat qavs ichida, qiymat turi
undan keyin.
Mavjud kalitga yozsangiz, qiymat almashadi; yangi kalitga yozsangiz, u qo'shiladi.
Bo'sh map yaratish #
package main
import "fmt"
func main() {
ballar := make(map[string]int)
ballar["Kamola"] = 95
fmt.Println(ballar)
var buzuq map[string]int
fmt.Println(buzuq == nil, len(buzuq))
fmt.Println(buzuq["yoq"])
}
map[Kamola:95]
true 0
0
var buzuq map[string]int - bu nil map. Undan o'qish
xavfsiz (nol qiymat qaytadi), lekin unga yozish dasturni
to'xtatadi:
panic: assignment to entry in nil map
Bu slice bilan farq qiladigan joy: nil slicega append qilish
mumkin edi, nil map ga esa yozib bo'lmaydi.
Shuning uchun map ni doim make bilan yoki map[string]int{}
shaklida yarating.
Kalit bor-yo'qligini bilish #
package main
import "fmt"
func main() {
ballar := map[string]int{"Malika": 88, "Aziza": 0}
fmt.Println(ballar["Malika"])
fmt.Println(ballar["Dilnoza"])
ball, bormi := ballar["Aziza"]
fmt.Println(ball, bormi)
ball2, bormi2 := ballar["Dilnoza"]
fmt.Println(ball2, bormi2)
}
88
0
0 true
0 false
Mana muammo: ballar["Dilnoza"] ham 0 beradi, ballar["Aziza"]
ham. Lekin birinchisi yo'q, ikkinchisi esa haqiqatan nolga
teng.
Ularni ajratish uchun ikkinchi qiymat olinadi. Bu shakl "comma-ok" deb ataladi.
Bu shaklni Go da uch joyda ko'rasiz:
qiymat, bormi := map[kalit]
qiymat, ochiq := <-kanal
qiymat, mos := interfeys.(Tur)
Uchalasida ham ikkinchi qiymat bool va u "amal muvaffaqiyatli
bo'ldimi" degan savolga javob beradi.
Kanallarni 19-, tur tekshiruvini 13-bo'limda ko'ramiz.
Tekshirib ishlatish #
package main
import "fmt"
func main() {
narxlar := map[string]int{
"Olma": 12000,
"Anor": 18000,
}
if narx, bormi := narxlar["Olma"]; bormi {
fmt.Println("Olma narxi:", narx)
}
if _, bormi := narxlar["Uzum"]; !bormi {
fmt.Println("Uzum topilmadi")
}
}
Olma narxi: 12000
Uzum topilmadi
5-bo'limdagi boshlang'ich qismli if bu yerda juda qulay: tekshiruv
va ishlatish bitta blokda.
O'chirish #
package main
import "fmt"
func main() {
shaharlar := map[string]string{
"NAM": "Namangan",
"AND": "Andijon",
"BUX": "Buxoro",
}
delete(shaharlar, "AND")
fmt.Println(len(shaharlar))
delete(shaharlar, "YOQ")
fmt.Println(len(shaharlar))
clear(shaharlar)
fmt.Println(len(shaharlar))
}
2
2
0
delete mavjud bo'lmagan kalitni o'chirishga urinsa, hech narsa
qilmaydi va xato ham bermaydi.
clear - hammasini o'chiradi. U Go 1.21 da qo'shilgan.
Tartib - ataylab tasodifiy #
package main
import "fmt"
func main() {
yoshlar := map[string]int{
"Husanboy": 25,
"Malika": 20,
"Nodira": 22,
}
fmt.Println(yoshlar)
fmt.Println(len(yoshlar))
}
map[Husanboy:25 Malika:20 Nodira:22]
3
Bu yerda natija saralangan ko'rinadi - lekin bu fmt ning
xizmati, map ning emas.
fmt.Println(yoshlar) map ni chop etganda, fmt paketi kalitlarni
o'zi saralaydi. Shuning uchun yuqoridagi natija barqaror.
Lekin range bilan yurganingizda tartib kafolatlanmaydi:
for kalit := range yoshlar {
fmt.Println(kalit)
}
Bu kod har safar boshqa tartibda chiqaradi. Bir xil dastur, bir xil ma'lumot - lekin har ishga tushirishda boshqa natija.
Bu xato emas, balki ataylab qilingan. Go jamoasi tartibni qasddan tasodifiy qildi, chunki aks holda dasturchilar unga bilmasdan tayanib qolar edi. Keyin esa Go ning ichki tuzilishi o'zgarganda ularning kodi buzilardi.
Tartib kerak bo'lsa, uni o'zingiz ta'minlaysiz.
Saralab chiqarish #
package main
import (
"fmt"
"slices"
)
func main() {
yoshlar := map[string]int{
"Husanboy": 25,
"Malika": 20,
"Nodira": 22,
"Aziza": 19,
}
kalitlar := make([]string, 0, len(yoshlar))
for kalit := range yoshlar {
kalitlar = append(kalitlar, kalit)
}
slices.Sort(kalitlar)
for _, kalit := range kalitlar {
fmt.Printf("%-10s %d\n", kalit, yoshlar[kalit])
}
}
Aziza 19
Husanboy 25
Malika 20
Nodira 22
Bu standart Go naqshi: kalitlarni yig', sarala, keyin yur.
Uni har safar qo'lda yozish shart emas - maps paketi yordam
beradi.
maps paketi #
package main
import (
"fmt"
"maps"
"slices"
)
func main() {
narxlar := map[string]int{
"Olma": 12000,
"Anor": 18000,
"Uzum": 22000,
}
kalitlar := slices.Sorted(maps.Keys(narxlar))
fmt.Println(kalitlar)
qiymatlar := slices.Sorted(maps.Values(narxlar))
fmt.Println(qiymatlar)
nusxa := maps.Clone(narxlar)
nusxa["Olma"] = 1
fmt.Println(narxlar["Olma"], nusxa["Olma"])
}
[Anor Olma Uzum]
[12000 18000 22000]
12000 1
maps.Keys kalitlarni ketma-ketlik sifatida qaytaradi,
slices.Sorted esa uni saralangan slicega aylantiradi.
Bu ikki paket Go 1.21-1.23 da qo'shilgan; eski Go da yuqoridagi qo'lda yozilgan shaklni ishlatasiz.
Map ham ko'rsatkich kabi #
package main
import "fmt"
func qoshimcha(m map[string]int) {
m["yangi"] = 100
}
func main() {
ballar := map[string]int{"eski": 50}
qoshimcha(ballar)
fmt.Println(len(ballar), ballar["yangi"])
}
2 100
& yozilmagan, lekin o'zgarish saqlandi. Map ichida ham
ma'lumotga ko'rsatkich bor - xuddi slice kabi.
nusxa := asl deb yozsangiz, ikkala o'zgaruvchi ham bitta map
ga ko'rsatadi. Biriga yozsangiz, ikkinchisida ham ko'rinadi.
Haqiqiy nusxa uchun maps.Clone(asl) ishlating - yuqoridagi
misolda shunday qilingan.
Murakkabroq qiymatlar #
package main
import (
"fmt"
"maps"
"slices"
)
func main() {
guruhlar := map[string][]string{
"A": {"Malika", "Nodira"},
"B": {"Husanboy"},
}
guruhlar["B"] = append(guruhlar["B"], "Aziza")
guruhlar["C"] = append(guruhlar["C"], "Kamola")
for _, g := range slices.Sorted(maps.Keys(guruhlar)) {
fmt.Printf("%s: %v\n", g, guruhlar[g])
}
}
A: [Malika Nodira]
B: [Husanboy Aziza]
C: [Kamola]
Diqqat qiling: guruhlar["C"] hali mavjud emas edi, lekin append
ishladi.
Sababi - mavjud bo'lmagan kalit nil slice qaytaradi, nil slicega
esa append qilish mumkin (9-bo'lim).
To'plam yasash #
package main
import (
"fmt"
"slices"
)
func main() {
korilgan := map[string]bool{}
sozlar := []string{"olma", "anor", "olma", "uzum", "anor"}
takrorsiz := []string{}
for _, s := range sozlar {
if !korilgan[s] {
korilgan[s] = true
takrorsiz = append(takrorsiz, s)
}
}
fmt.Println(takrorsiz)
fmt.Println(len(korilgan))
saralangan := slices.Clone(takrorsiz)
slices.Sort(saralangan)
fmt.Println(saralangan)
}
[olma anor uzum]
3
[anor olma uzum]
Go da alohida "to'plam" turi yo'q. Uning o'rniga
map[string]bool yoki map[string]struct{} ishlatiladi.
Bu yerda korilgan[s] mavjud bo'lmagan kalit uchun false
qaytargani ish beradi - qo'shimcha tekshiruv kerak emas.
Ba'zan map[string]struct{} shaklini ko'rasiz. struct{} - bo'sh
struktura, u umuman joy egallamaydi.
bool har bir element uchun bir bayt oladi; million elementli
to'plamda bu bir megabayt. struct{} esa nol.
Farqi shundaki, yozish uzunroq bo'ladi:
korilgan[s] = struct{}{}. Shuning uchun kichik to'plamlar uchun
bool yetarli va o'qishliroq.
- Ism va yoshni saqlaydigan map yarating.
nilmap ga yozishga urinib, vahima matnini ko'ring.- comma-ok bilan mavjud va mavjud bo'lmagan kalitni ajrating.
- Nolga teng qiymat va yo'q kalit farqini ko'rsating.
deletevaclearni sinang.rangebilan bir necha marta chiqarib, tartib o'zgarishini ko'ring.- Kalitlarni saralab, tartibli chiqaring.
maps.Clonebilan mustaqil nusxa oling.map[string][]stringbilan guruhlar tuzing.- Map yordamida takrorlarni olib tashlang.
Xulosa #
map[kalit]qiymat- kalit bo'yicha saqlash;makeyoki literal bilan yaratiladi.nilmap dan o'qish mumkin, yozib bo'lmaydi - bu vahima keltiradi.- Mavjud bo'lmagan kalit nol qiymat beradi; borligini bilish uchun comma-ok shakli.
deleteyo'q kalitga befarq;clearhammasini o'chiradi.rangebo'yicha tartib ataylab tasodifiy;fmtesa chop etishda kalitlarni o'zi saralaydi.- Tartib kerak bo'lsa: kalitlarni yig'ib,
slices.Sortbilan saralang. - Map ichida ko'rsatkich bor - funksiyaga uzatilganda o'zgarish
saqlanadi; nusxa uchun
maps.Clone. - To'plam uchun
map[string]boolyokimap[string]struct{}ishlatiladi.
Keyingi bo'limda strukturalarni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.