Tarkibga o'tish

05 β€” To'plamlar: List, Set, Map

⬅️ Oldingi: 04 β€” Funksiyalar Β· 🏠 README Β· Keyingi: 06 β€” Null safety ➑️

Bu bobda: ko'p qiymatni birga saqlashning uchta asosiy yo'lini o'rganamiz — List (tartibli ro'yxat, masalan xarid ro'yxati), Set (takrorsiz to'plam, masalan mehmonlar ro'yxati) va Map (kalit→qiymat lug'ati, masalan telefon kitobi). So'ng ularning ustidagi "kuchli vositalar" — map, where, fold kabi iterable metodlarni va Flutter UI'sida har kuni ishlatiladigan spread ... hamda collection-if / collection-for sintaksisini ko'ramiz.


Nega to'plam kerak?

Hozirgacha biz bitta o'zgaruvchida bitta qiymat saqladik:

String meva = 'olma';

Lekin haqiqiy dasturda ko'pincha bir nechta qiymat kerak bo'ladi. Do'konga borayotganingizdagi xarid ro'yxatini tasavvur qiling: olma, non, sut, tuxum... Bularning har biriga alohida o'zgaruvchi ochsak β€” meva1, meva2, meva3 β€” bu nochor yo'l. Nechta narsa borligini oldindan bilmaymiz, ularni siklda aylanib chiqib bo'lmaydi, qo'shish-o'chirish ham qiyin.

To'plam (collection) β€” bu aynan shu muammoni hal qiladigan idish: u ichida ko'p qiymatni birga saqlaydi va ular bilan birgalikda ishlash imkonini beradi. Dart'da uchta asosiy to'plam bor, va ularning farqi β€” ma'lumotni qanday tartibga solishida:

Dart'ning uchta to'plami: List tartibli va indeksli, Set takrorsiz va tartibsiz, Map kalit-qiymat juftliklaridan iborat

Endi har birini alohida, sekin-asta ko'rib chiqamiz.


List β€” tartibli ro'yxat

List (ro'yxat) β€” eng ko'p ishlatiladigan to'plam. U xuddi raqamlangan kichik qutilar qatori kabi: har bir qiymat o'z o'rnida turadi va siz qaysi tartibda qo'ygan bo'lsangiz, shu tartibda saqlanadi.

Ro'yxatni kvadrat qavs [ ] ichida, qiymatlarni vergul bilan ajratib yozamiz:

List<String> xarid = ['olma', 'non', 'sut'];
print(xarid);   // [olma, non, sut]

List<String> β€” "stringlardan iborat ro'yxat" degani. Burchakli qavs ichidagi <String> β€” ro'yxat ichida nima turishini aytadi (bu generic deyiladi, hozir shunchaki "ichidagi tip" deb tushuning). Agar List<int> desangiz β€” sonlar ro'yxati, List<double> β€” kasr sonlar ro'yxati.

πŸ’‘ Dart ko'pincha tipni o'zi topadi. var xarid = ['olma', 'non']; desangiz, Dart boshlang'ich qiymatlarga qarab buni List<String> deb biladi. Lekin tipni ochiq yozish β€” kodingizni o'qigan odam (va kelajakdagi o'zingiz) uchun aniqroq. (var, final va tip yozish farqini 04-bobdan eslang.)

Indeks β€” har qiymatning raqami

Ro'yxatdagi har bir element o'z indeksiga (tartib raqamiga) ega. Eng muhim qoida β€” esda tuting:

πŸ“Œ Indeks 0 dan boshlanadi, 1 dan emas. Ya'ni birinchi element [0], ikkinchisi [1], uchinchisi [2].

List<String> xarid = ['olma', 'non', 'sut'];

print(xarid[0]);   // olma  (birinchi)
print(xarid[1]);   // non   (ikkinchi)
print(xarid[2]);   // sut   (uchinchi)

Nega 0 dan? Buni "boshidan necha qadam siljiganingiz" deb tushuning: birinchi element boshning o'zida β€” 0 qadam, ikkinchisi 1 qadam keyin. Bu ko'pchilik dasturlash tillarida shunday, va boshida g'alati tuyulsa-da, tez ko'nikasiz.

⚠️ Mavjud bo'lmagan indeksni so'rasangiz, dastur xato beradi (crash). Uch elementli ro'yxatda xarid[3] β€” bunday element yo'q:

print(xarid[3]);
// RangeError (index): Index out of range: index should be less than 3: 3

Ro'yxat haqida ma'lumot olish

List<String> xarid = ['olma', 'non', 'sut'];

print(xarid.length);            // 3      β€” nechta element bor
print(xarid.first);             // olma   β€” birinchi element
print(xarid.last);              // sut    β€” oxirgi element
print(xarid.isEmpty);           // false  β€” bo'shmi?
print(xarid.contains('non'));   // true   β€” 'non' ichida bormi?
print(xarid.indexOf('sut'));    // 2      β€” 'sut' qaysi indeksda?

πŸ“Œ xarid.length β€” element soni; oxirgi elementning indeksi esa har doim length - 1 (bu yerda 2). xarid.first aslida xarid[0] bilan bir xil β€” shunchaki o'qishga qulayroq.

Ro'yxatni o'zgartirish: qo'shish va o'chirish

Oddiy ro'yxat o'zgaruvchan (mutable) β€” ya'ni keyinchalik element qo'shsa, o'chirsa bo'ladi:

List<String> xarid = ['olma', 'non'];

xarid.add('sut');             // oxiriga qo'shadi      -> [olma, non, sut]
xarid.insert(0, 'tuxum');     // 0-indeksga joylaydi   -> [tuxum, olma, non, sut]
xarid.remove('non');          // qiymat bo'yicha o'chiradi -> [tuxum, olma, sut]
xarid.removeAt(0);            // indeks bo'yicha o'chiradi  -> [olma, sut]

print(xarid);                 // [olma, sut]
  • .add(x) β€” x ni ro'yxat oxiriga qo'shadi.
  • .insert(i, x) β€” x ni i-indeksga kiritadi, qolganlari bir qadam o'ngga suriladi.
  • .remove(x) β€” birinchi uchragan x qiymatini o'chiradi.
  • .removeAt(i) β€” i-indeksdagi elementni o'chiradi.

O'zgarmas ro'yxat β€” const

Ba'zan ro'yxat hech qachon o'zgarmasligi kerak β€” masalan, hafta kunlari yoki sozlamalar. Bunday holda const ishlatamiz. const ro'yxatga add qilishga urinish xato beradi:

const kunlar = ['Dush', 'Sesh', 'Chor'];
kunlar.add('Pay');
// Unsupported operation: Cannot add to an unmodifiable list

πŸ’‘ Qoida: ro'yxat o'zgarmasligi kerak bo'lsa β€” const qiling. Bu kodingizni xavfsizroq qiladi: "men buni hech qaerda o'zgartirmayman" degan kafolat beradi va tasodifiy o'zgarishlardan himoyalaydi.

Ro'yxatni aylanib chiqish β€” for-in

Ro'yxatdagi har bir elementni navbatma-navbat ko'rib chiqish uchun for-in siklidan foydalanamiz (siklarni 04-bob oldidagi 03-bobda ko'rgansiz):

List<String> xarid = ['olma', 'non', 'sut'];

for (var meva in xarid) {
  print('Sotib olish: $meva');
}
// Sotib olish: olma
// Sotib olish: non
// Sotib olish: sut

for (var meva in xarid) β€” "ro'yxatdagi har bir elementni navbat bilan meva deb atab, ich qismni bajar" deb o'qiladi. Bu indeks bilan o'ralashishdan ancha tozaroq.


Set β€” takrorsiz to'plam

Endi boshqa muammoni tasavvur qiling: to'yga mehmonlar ro'yxatini tuzayapsiz. Bir odamni ikki marta yozsangiz, u baribir bitta mehmon. Tartib ham muhim emas β€” kim avval kelishi katta gap emas. Bizga kerak: takrorsiz to'plam.

Mana shu yerda Set (to'plam) ishlaydi. U ikkita maxsus xususiyatga ega:

  1. Takror bo'lmaydi β€” bir xil qiymatni ikki marta qo'shsangiz, ikkinchisi e'tiborga olinmaydi.
  2. Tartib kafolatlanmaydi β€” Set indeks bilan ishlamaydi (set[0] yo'q).

Set ham figurali qavs { } ichida yoziladi:

Set<String> mehmonlar = {'Ali', 'Vali', 'Guli'};

mehmonlar.add('Ali');      // allaqachon bor β€” hech narsa qo'shilmaydi
mehmonlar.add('Salim');    // yangi β€” qo'shiladi

print(mehmonlar);          // {Ali, Vali, Guli, Salim}
print(mehmonlar.length);   // 4  β€” 'Ali' takrorlanmadi

πŸ“Œ Diqqat: bo'sh {} β€” bu Set emas, Map (keyingi bo'lim). Bo'sh Set yozish uchun tipni ochiq ayting: Set<String> bosh = {}; yoki <String>{}.

Set qachon List'dan ustun?

Set'ning yana bir kuchli tomoni β€” .contains juda tez ishlaydi. List'da contains butun ro'yxatni boshdan-oxir tekshiradi (1000 element bo'lsa, 1000 ta solishtirish bo'lishi mumkin). Set esa qiymatni deyarli bir zumda topadi. Shuning uchun "bu narsa to'plamda bormi?" degan savol ko'p bo'lsa β€” Set tanlang.

Eng keng tarqalgan amaliy ish β€” takrorlarni tozalash (dedupe). List'ni Set'ga aylantiring, takrorlar o'z-o'zidan yo'qoladi:

List<int> sonlar = [1, 2, 2, 3, 3, 3, 4];
Set<int> noyob = sonlar.toSet();   // takrorlar tushib qoladi
print(noyob);                      // {1, 2, 3, 4}

// Yana ro'yxat kerak bo'lsa, qaytaring:
List<int> tozalangan = noyob.toList();
print(tozalangan);                 // [1, 2, 3, 4]

To'plam amallari: birlashtirish va kesishish

Set matematik to'plamlar kabi ishlaydi:

Set<String> aDars = {'Matematika', 'Fizika', 'Tarix'};
Set<String> bDars = {'Fizika', 'Tarix', 'Geografiya'};

print(aDars.union(bDars));        // ikkalasining hammasi (birlashma)
// {Matematika, Fizika, Tarix, Geografiya}

print(aDars.intersection(bDars)); // faqat ikkisida ham bor (kesishma)
// {Fizika, Tarix}

print(aDars.difference(bDars));   // a'da bor, b'da yo'q (ayirma)
// {Matematika}

union β€” birlashtirish, intersection β€” umumiy qism, difference β€” faqat birinchisidagi farq. Bular "ikki guruhda kim umumiy?" kabi savollarga javob beradi.


Map — kalit→qiymat lug'ati

Telefon kitobini tasavvur qiling. Unda siz ism bilan qidirasiz va raqam topasiz: "Ali" β†’ "+998 90 123-45-67". Bu yerda muhimi indeks emas (Ali nechanchi yozilgani sizga qiziq emas), balki nom orqali topish.

Map (lug'at, xarita) aynan shunday ishlaydi: har bir qiymatga kalit (key) biriktiriladi, va siz qiymatni o'sha kalit orqali olasiz. Buni so'zlik (lug'at) deb ham tasavvur qilishingiz mumkin: so'z (kalit) β†’ ta'rifi (qiymat).

Map ham figurali qavs ichida, lekin har juftlik kalit: qiymat ko'rinishida:

Map<String, dynamic> odam = {
  'ism': 'Ali',
  'yosh': 25,
  'shahar': 'Toshkent',
};

print(odam['ism']);     // Ali
print(odam['yosh']);    // 25

Map<String, int> ikkita tip oladi: birinchisi β€” kalit tipi, ikkinchisi β€” qiymat tipi. Yuqorida Map<String, dynamic> ishlatdik, chunki qiymatlar har xil (string va son aralash); dynamic "istalgan tip" degani. Agar barcha qiymatlar bir xil bo'lsa, aniqroq yozing:

Map<String, int> yoshlar = {
  'Ali': 25,
  'Vali': 30,
  'Guli': 22,
};

print(yoshlar['Vali']);   // 30

⚠️ Mavjud bo'lmagan kalitni so'rasangiz, Dart xato bermaydi β€” null qaytaradi (null β€” "qiymat yo'q" degani, keyingi 06-bobda chuqur o'rganamiz):

print(yoshlar['Karim']);   // null  β€” bunday kalit yo'q

Qo'shish, o'zgartirish, o'chirish

Map<String, int> yoshlar = {'Ali': 25};

yoshlar['Vali'] = 30;       // yangi juftlik qo'shadi
yoshlar['Ali'] = 26;        // mavjud kalitni yangilaydi (qiymat o'zgaradi)
yoshlar.remove('Vali');     // juftlikni o'chiradi

print(yoshlar);             // {Ali: 26}

πŸ“Œ Diqqat: yoshlar['Ali'] = 26 β€” agar 'Ali' allaqachon bor bo'lsa, eski qiymat ustiga yoziladi; yo'q bo'lsa, yangi juftlik qo'shiladi. Kalitlar Map ichida takrorlanmaydi β€” bitta kalitda faqat bitta qiymat bo'ladi.

.containsKey bilan kalit borligini xavfsiz tekshiring:

if (yoshlar.containsKey('Ali')) {
  print('Ali bor, yoshi: ${yoshlar['Ali']}');
}

Map'ni aylanib chiqish

Map'da uchta foydali bo'lim bor: .keys (kalitlar), .values (qiymatlar) va .entries (juftliklar):

Map<String, int> yoshlar = {'Ali': 25, 'Vali': 30};

print(yoshlar.keys);     // (Ali, Vali)
print(yoshlar.values);   // (25, 30)

// Har juftlikni aylanib chiqish:
for (var juft in yoshlar.entries) {
  print('${juft.key} -> ${juft.value} yosh');
}
// Ali -> 25 yosh
// Vali -> 30 yosh

Har bir entry (juftlik)ning .key (kaliti) va .value (qiymati) bor. Bu β€” Map'ni to'liq ko'rib chiqishning eng toza yo'li.


Iterable metodlari β€” kuchli vositalar

Mana endi eng qiziq qismga keldik. List va Set'ning ustida bir guruh kuchli metod bor (ular birga "iterable metodlari" deyiladi). Bular yordamida siklning butun mantig'ini bitta qatorda ifodalash mumkin.

Bu metodlar funksiyani parametr sifatida oladi β€” ya'ni ular yuqori-tartibli funksiyalar. Agar (x) => ... ko'rinishidagi anonim funksiya va arrow yozuvini eslamasangiz, 04-bobga qaytib o'qing β€” shu yerda har qadamda kerak bo'ladi.

.map β€” har elementni o'zgartirish

.map har bir elementni yangi qiymatga aylantiradi va yangi ketma-ketlik qaytaradi (asl ro'yxatga tegmaydi). Diqqat: bu Map (lug'at) bilan adashtirmang β€” bu .map() metodi.

Ismlar ro'yxatini salomlashuvlar ro'yxatiga aylantiramiz:

List<String> ismlar = ['Ali', 'Vali', 'Guli'];

var salomlar = ismlar.map((ism) => 'Salom, $ism!').toList();
print(salomlar);
// [Salom, Ali!, Salom, Vali!, Salom, Guli!]

ismlar.map((ism) => '...') β€” "har bir ism uchun shu ifodani hisobla" degani. Oxiridagi .toList() natijani yana ro'yxatga aylantiradi (buning sababini quyida tushuntiramiz).

.where β€” filtrlash

.where faqat shartni qondiradigan elementlarni qoldiradi (boshqa tillarda bu "filter" deyiladi):

List<int> sonlar = [1, 2, 3, 4, 5, 6];

var juftlar = sonlar.where((n) => n % 2 == 0).toList();
print(juftlar);   // [2, 4, 6]   β€” faqat juft sonlar

(n) => n % 2 == 0 β€” "n juftmi?" (2 ga qoldiqsiz bo'linadimi). true qaytargan elementlar qoladi, qolgani tushib ketadi.

Zanjirlash (chaining) β€” quvur kabi

Eng kuchli tomoni: bu metodlarni ketma-ket ulash mumkin. Bir metod natijasi keyingisiga "quvur" orqali o'tadi:

Iterable quvuri: [1,2,3,4] ro'yxati .where (juftlarni saqlash) orqali [2,4] ga, so'ng .map (10 ga ko'paytirish) orqali [20,40] ga aylanadi

var natija = [1, 2, 3, 4]
    .where((x) => x % 2 == 0)   // juftlarni qoldir -> (2, 4)
    .map((x) => x * 10)         // 10 ga ko'paytir   -> (20, 40)
    .toList();                  // ro'yxatga aylantir

print(natija);   // [20, 40]

Buni chapdan o'ngga, "avval filtrla, keyin o'zgartir, keyin ro'yxatga aylantir" deb o'qing. Bir nechta for siklisiz, qo'shimcha o'zgaruvchisiz β€” tiniq va o'qishga oson.

πŸ’‘ Nega .toList()? .map va .where aslida darrov ishlamaydi β€” ular "kechiktirilgan" (lazy) Iterable qaytaradi va faqat siz natijani so'raganingizda hisoblaydi. .toList() (yoki .toSet()) ularni "majburlab", haqiqiy ro'yxatga aylantiradi. Amalda: natijani saqlamoqchi yoki bir necha marta ishlatmoqchi bo'lsangiz β€” .toList() qo'shing.

Yana to'rt foydali metod

List<int> baholar = [5, 4, 3, 5, 2];

// .forEach β€” har element uchun amal bajaradi (natija qaytarmaydi)
baholar.forEach((b) => print('Baho: $b'));

// .fold β€” hammasini bitta qiymatga "yig'adi" (boshlang'ich qiymat bilan)
int jami = baholar.fold(0, (yigindi, b) => yigindi + b);
print(jami);   // 19

// .any β€” kamida bittasi shartni qondiradimi?
print(baholar.any((b) => b == 2));    // true  (2 bor)

// .every β€” hammasi shartni qondiradimi?
print(baholar.every((b) => b >= 3));  // false (2 bor, u 3'dan kichik)
  • .forEach β€” har element ustida amal bajaradi (for-in ning qisqa shakli).
  • .fold β€” barcha elementni bitta natijaga to'playdi (yig'indi, ko'paytma, eng katta...). Birinchi argument β€” boshlang'ich qiymat (0), keyin har qadamda yig'indini yangilaydi. (.reduce ham xuddi shunday, lekin boshlang'ich qiymatsiz; bo'sh ro'yxatda xato berishi mumkin, shuning uchun .fold xavfsizroq.)
  • .any β€” "kamida bittasi?"; .every β€” "hammasimi?".

πŸ’‘ Bu metodlar Flutter'da hamma joyda uchraydi. Masalan, serverdan kelgan mahsulotlar ro'yxatini ekrandagi kartochkalar ro'yxatiga aylantirish β€” bu aynan .map. Shuning uchun ularni hozir mustahkam o'zlashtiring.


Spread va collection-if / collection-for

Endi Flutter'ga to'g'ridan-to'g'ri ko'prik bo'ladigan, juda muhim sintaksisni ko'ramiz. Bular ro'yxatni yaratishning o'zi ichida ishlaydi.

Spread ... β€” ro'yxatni "yoyish"

... (spread operatori) bir ro'yxatning barcha elementlarini boshqa ro'yxat ichiga "to'kib" beradi:

List<int> birinchi = [1, 2, 3];
List<int> ikkinchi = [4, 5];

List<int> birga = [...birinchi, ...ikkinchi, 6];
print(birga);   // [1, 2, 3, 4, 5, 6]

...birinchi β€” "birinchining hamma elementini shu yerga qo'y" degani. Ikki ro'yxatni birlashtirish yoki ro'yxat boshiga/oxiriga qo'shimcha element qo'shishning eng toza yo'li.

collection-for β€” ro'yxat ichida sikl

Odatda ma'lumotdan ro'yxat qurish uchun bo'sh ro'yxat ochib, siklda .add qilardik. collection-for buni bir qadamga qisqartiradi β€” forni to'g'ridan-to'g'ri kvadrat qavs ichida yozasiz:

collection-for: list literal ichidagi for sikli [for (var n in [1,2,3]) n*n] ifodasini [1,4,9] ro'yxatiga aylantiradi, va xuddi shu naqsh Flutter children ro'yxatini quradi

// Eski uslub β€” uzun:
List<int> kvadratlar = [];
for (var n in [1, 2, 3]) {
  kvadratlar.add(n * n);
}

// collection-for β€” bir qatorda, aniq:
List<int> kvadratlar2 = [for (var n in [1, 2, 3]) n * n];

print(kvadratlar2);   // [1, 4, 9]

collection-if β€” shartli element

collection-if bilan element ro'yxatga faqat shart bajarilganda qo'shiladi:

bool chegirmaBor = true;

List<String> menyu = [
  'Asosiy taom',
  'Salat',
  if (chegirmaBor) 'BONUS: Bepul shirinlik',   // faqat shart true bo'lsa
];

print(menyu);
// [Asosiy taom, Salat, BONUS: Bepul shirinlik]

chegirmaBor false bo'lganida, oxirgi element ro'yxatga umuman kirmaydi.

Nega bu Flutter uchun shunchalik muhim?

Flutter'da ekranni quryotganda children (bolalar) deb nomlangan widget ro'yxatini beryapsiz. Aynan shu yerda spread, collection-if va collection-for kunni qutqaradi. Hozir bu kod sizga notanish β€” bu normal, biz Flutter'ga keyinroq o'tamiz β€” lekin naqshga e'tibor bering, u tanish:

Column(
  children: [
    Text('Sarlavha'),
    if (kirgan) LogoutTugma(),                         // shartli widget
    for (var m in mahsulotlar) MahsulotKarta(m),       // ro'yxatdan widgetlar
    ...qoshimchaWidgetlar,                             // boshqa ro'yxatni yoyish
  ],
)

Bu β€” "ma'lumotlar ro'yxatini ekrandagi widgetlar ro'yxatiga aylantirish". Bugun List, collection-for va collection-if'ni o'rganganingiz uchun, Flutter UI yozishni boshlaganingizda bu siz uchun yangi narsa bo'lmaydi β€” shunchaki yangi joyda ishlatasiz.


Xulosa

  • List [ ] β€” tartibli, indeksli ro'yxat. Indeks 0 dan boshlanadi. .add/.remove/.insert, .length, .first/.last, .contains. O'zgarmasligi kerak bo'lsa β€” const. for-in bilan aylaniladi.
  • Set { } β€” takrorsiz, tartibsiz to'plam. Takrorlarni avtomatik tashlaydi (.toSet() bilan dedupe), .contains tez, union/intersection/difference amallari bor.
  • Map {kalit: qiymat} β€” kalitβ†’qiymat lug'ati (telefon kitobi). map['kalit'] bilan olasiz (yo'q kalit null qaytaradi), .keys/.values/.entries, .containsKey.
  • Iterable metodlari: .map (o'zgartirish), .where (filtrlash), .fold/.reduce (yig'ish), .any/.every, .forEach. Ularni zanjirlash mumkin; natijani .toList() bilan majburlang.
  • Spread ..., collection-if va collection-for β€” ro'yxatni yaratishning ichida ishlaydi va Flutter'da children qurishda har kuni ishlatiladi.

Keyingi bobda Dart'ning eng muhim xavfsizlik mexanizmiga β€” null safetyga o'tamiz: "qiymat yo'q" (null) holatini Dart qanday qilib xatoga aylanishidan oldin ushlab qolishini ko'ramiz.


Mashqlar

Har bir mashqni avval o'zingiz yeching, keyin yechimga qarang. Kod misollarini DartPad'da yoki dart run bilan ishga tushirib, natijani o'z ko'zingiz bilan ko'ring.

  1. List<String> tipida tillar ro'yxatini yarating va unga 'Dart', 'Python', 'JavaScript' qo'shing. So'ng .add bilan 'Go' qo'shing, ikkinchi elementni ([1]) chop eting va .lengthni ko'rsating.
  2. [10, 20, 30, 40, 50] ro'yxatidan .where bilan faqat 25 dan katta sonlarni ajrating, so'ng .map bilan har birini 2 ga ko'paytiring. Natijani .toList() bilan ro'yxatga aylantirib chop eting (zanjirlashdan foydalaning).
  3. [1, 1, 2, 3, 3, 3, 4, 5, 5] ro'yxatidagi takrorlarni Set yordamida tozalang va natijani yana saralangan ro'yxat ko'rinishida (.toList()) chop eting.
  4. Map<String, int> tipida narxlar lug'atini yarating: 'olma': 8000, 'non': 3000, 'sut': 12000. So'ng: (a) 'non' narxini chop eting; (b) 'tuxum': 15000 qo'shing; (c) .entries bilan barcha mahsulot va narxlarni "olma β€” 8000 so'm" ko'rinishida chop eting.
  5. ismlar = ['ali', 'vali', 'guli'] ro'yxatini collection-for ishlatib, har bir ismni bosh harf bilan boshlangan salomga aylantiring (masalan 'Salom, ali!'). (Maslahat: [for (...) ...].)
  6. collection-if bilan ishlang: bool adminMi o'zgaruvchisi bo'lsin. ['Bosh sahifa', 'Profil'] menyusiga adminMi true bo'lgandagina 'Admin panel' bandini qo'shing. adminMi ni true va false qilib, ikkala natijani ko'ring.

Yechimlar

Yechim β€” 1
void main() {
  List<String> tillar = ['Dart', 'Python', 'JavaScript'];
  tillar.add('Go');

  print(tillar[1]);        // Python  (indeks 0 dan boshlanadi!)
  print(tillar.length);    // 4
  print(tillar);           // [Dart, Python, JavaScript, Go]
}

E'tibor bering: [1] β€” ikkinchi element, chunki birinchisi [0]. Ro'yxat o'zgaruvchan bo'lgani uchun .add ishladi.

Yechim β€” 2
void main() {
  var natija = [10, 20, 30, 40, 50]
      .where((n) => n > 25)    // -> (30, 40, 50)
      .map((n) => n * 2)       // -> (60, 80, 100)
      .toList();

  print(natija);   // [60, 80, 100]
}

Quvurni chapdan o'ngga o'qing: avval filtrlash, keyin o'zgartirish. .toList() bo'lmasa, natija "kechiktirilgan" Iterable bo'lib qolardi.

Yechim β€” 3
void main() {
  List<int> sonlar = [1, 1, 2, 3, 3, 3, 4, 5, 5];

  Set<int> noyob = sonlar.toSet();   // takrorlar tushadi -> {1, 2, 3, 4, 5}
  List<int> natija = noyob.toList(); // -> [1, 2, 3, 4, 5]

  print(natija);   // [1, 2, 3, 4, 5]
}

.toSet() β€” dedupe qilishning eng oson yo'li. Bu misolda kiritma allaqachon tartiblangani uchun natija ham tartibli chiqadi; har doim kafolat kerak bo'lsa, natija.sort() qo'shing.

Yechim β€” 4
void main() {
  Map<String, int> narxlar = {
    'olma': 8000,
    'non': 3000,
    'sut': 12000,
  };

  // (a)
  print(narxlar['non']);   // 3000

  // (b)
  narxlar['tuxum'] = 15000;

  // (c)
  for (var juft in narxlar.entries) {
    print('${juft.key} β€” ${juft.value} so\'m');
  }
  // olma β€” 8000 so'm
  // non β€” 3000 so'm
  // sut β€” 12000 so'm
  // tuxum β€” 15000 so'm
}

.entries har juftlikning .key (mahsulot nomi) va .value (narx)ini beradi.

Yechim β€” 5
void main() {
  List<String> ismlar = ['ali', 'vali', 'guli'];

  List<String> salomlar = [
    for (var ism in ismlar) 'Salom, $ism!',
  ];

  print(salomlar);
  // [Salom, ali!, Salom, vali!, Salom, guli!]
}

collection-for bo'sh ro'yxat + .add ga ehtiyojni yo'qotadi. (Xuddi shu natijani ismlar.map((ism) => 'Salom, $ism!').toList() bilan ham olish mumkin β€” ikkala yo'l ham to'g'ri.)

Yechim β€” 6
void main() {
  bool adminMi = true;

  List<String> menyu = [
    'Bosh sahifa',
    'Profil',
    if (adminMi) 'Admin panel',
  ];

  print(menyu);
  // adminMi = true  -> [Bosh sahifa, Profil, Admin panel]
  // adminMi = false -> [Bosh sahifa, Profil]
}

adminMi false bo'lganda oxirgi band ro'yxatga umuman kirmaydi. Aynan shu naqshni keyinroq Flutter'da children ichida ishlatasiz: foydalanuvchi roli bo'yicha qaysi widget ko'rinishini boshqarish uchun.


⬅️ Oldingi: 04 β€” Funksiyalar Β· 🏠 README Β· Keyingi: 06 β€” Null safety ➑️