Dərs 15A Orta səviyyə

JavaScript-də massivlərin transformasiyası və filtrasiyası

map(), filter(), find() və digər funksional massiv metodları ilə məlumatları emal etməyi öyrənin

Nələri öyrənəcəksiniz

  • map() metodu ilə massiv elementlərini necə transformasiya edəcəyinizi öyrənəcəksiniz
  • filter() ilə şərtə uyğun elementləri seçməyi başa düşəcəksiniz
  • find() və findIndex() metodları ilə elementləri necə tapacağınızı biləcəksiniz
  • some() və every() ilə massivlərdə şərtləri necə yoxlayacağınızı öyrənəcəksiniz
  • Metod zəncirlərini necə effektiv istifadə edəcəyinizi başa düşəcəksiniz
  • Performans optimizasiyası və ən yaxşı təcrübələri öyrənəcəksiniz

01 Funksional massiv metodlarına giriş

JavaScript-də massivlər güclü daxili metodlara malikdir ki, bunlar məlumatları transformasiya etməyə, filtrləməyə və analiz etməyə imkan verir. Bu metodlar funksional proqramlaşdırma yanaşmasından istifadə edir və kodu daha oxunaqlı və təkrar istifadə oluna bilən edir.

Funksional metodların üstünlükləri

  • Daha oxunaqlı və anlaşıqlı kod
  • Deklarativ yanaşma - nə etmək istədiyinizi yazırsınız, necə olduğunu yox
  • Zəncirləmə imkanı - bir neçə əməliyyatı ardıcıl yerinə yetirmək
  • Orijinal massivi dəyişdirmir - yeni massiv qaytarır (dəyişməzlik)
Vacib qeydBu dərsdə öyrənəcəyimiz bütün metodlar (map, filter, find, və s.) orijinal massivi dəyişdirmir. Onlar həmişə yeni nəticə qaytarırlar.

02 map() - massivləri transformasiya etmək

map() metodu massivin hər bir elementinə funksiya tətbiq edərək yeni massiv yaradır. Bu metod orijinal massivi dəyişdirmir və həmişə eyni uzunluqda yeni massiv qaytarır.

Əsas istifadə

map() metodunun ən sadə istifadəsi hər bir elementi transformasiya etməkdir.

javascript
// Əsas map() istifadəsi
let numbers = [1, 2, 3, 4, 5];

// Hər bir ədədi 2-yə vurmaq
let doubled = numbers.map(num => num * 2);
console.log(doubled);     // Çıxış: [2, 4, 6, 8, 10]
console.log(numbers);     // Çıxış: [1, 2, 3, 4, 5] (dəyişməyib)

// Hər bir ədədi kvadrata yüksəltmək
let squared = numbers.map(num => num * num);
console.log(squared);     // Çıxış: [1, 4, 9, 16, 25]

// Mətnləri böyük hərfə çevirmək
let names = ['ali', 'vəli', 'həsən'];
let uppercased = names.map(name => name.toUpperCase());
console.log(uppercased);  // Çıxış: ['ALI', 'VƏLI', 'HƏSƏN']

Callback funksiyasının parametrləri

map() metoduna ötürülən callback funksiyası üç parametr qəbul edir:

javascript
let fruits = ['alma', 'armud', 'banan'];

// Bütün parametrlərdən istifadə
let result = fruits.map((element, index, array) => {
  console.log(`Element: ${element}`);
  console.log(`Element index: ${index}`);
  console.log(`Array length: ${array.length}`);
  return `${index + 1}. ${element}`;
});

console.log(result);
// Çıxış:
// 'Element: alma'
// 'Element index: 0'
// 'Array length: 3'
// 'Element: armud'
// 'Element index: 1'
// 'Array length: 3'
// 'Element: banan'
// 'Element index: 2'
// 'Array length: 3'
// [ '1. alma', '2. armud', '3. banan' ]

Parametrlər

  • element - Cari element (tək-tək hər element)
  • index - Cari elementin indeksi
  • array - Əsas massiv

Praktik nümunələr

map() metodu real layihələrdə tez-tez obyekt massivləri ilə işləyərkən istifadə olunur.

javascript
// Məhsul qiymətləri ilə işləmək
let products = [
  { name: 'Kitab', price: 20 },
  { name: 'Qələm', price: 5 },
  { name: 'Dəftər', price: 10 }
];

// 20% endirim tətbiq etmək
let discountedProducts = products.map(product => ({
  name: product.name,
  oldPrice: product.price,
  newPrice: product.price * 0.8  // 20% endirim
}));

console.log(discountedProducts);
// Çıxış:
// [
//   { name: 'Kitab', oldPrice: 20, newPrice: 16 },
//   { name: 'Qələm', oldPrice: 5, newPrice: 4 },
//   { name: 'Dəftər', oldPrice: 10, newPrice: 8 }
// ]

// Yalnız məhsul adlarını çıxarmaq
let productNames = products.map(product => product.name);
console.log(productNames);  // Çıxış: ['Kitab', 'Qələm', 'Dəftər']
Əhəmiyyətli məqammap() metodu həmişə orijinal massivlə eyni uzunluqda yeni massiv qaytarır. Əgər bəzi elementləri çıxarmaq istəyirsinizsə, filter() metodunu istifadə edin.

03 filter() - elementləri filtrləmək

filter() metodu verilmiş şərtə uyğun gələn bütün elementləri seçərək yeni massiv yaradır. Callback funksiyası true qaytardıqda element yeni massivə daxil olur, false qaytardıqda isə daxil olmur.

Əsas istifadə

filter() metodu şərtə uyğun elementləri seçmək üçün istifadə olunur.

javascript
// Ədədləri filtrləmək
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Yalnız cüt ədədləri saxlamaq
let even = numbers.filter(num => num % 2 === 0);
console.log(even);        // Çıxış: [2, 4, 6, 8, 10]

// 5-dən böyük ədədlər
let large = numbers.filter(num => num > 5);
console.log(large);       // Çıxış: [6, 7, 8, 9, 10]

console.log(numbers);     // Çıxış: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] (dəyişməyib)

Mürəkkəb şərtlər

filter() metodunda bir neçə şərti birləşdirərək daha mürəkkəb filtrlər yarada bilərsiniz.

javascript
let students = [
  { name: 'Ali', grade: 85, age: 20 },
  { name: 'Leyla', grade: 92, age: 19 },
  { name: 'Vəli', grade: 78, age: 21 },
  { name: 'Aynur', grade: 88, age: 20 }
];

// Keçən tələbələr (bal >= 80)
let passed = students.filter(student => student.grade >= 80);
console.log(passed);
// Çıxış: Ali, Leyla, Aynur

// Bir neçə şərt birləşdirmək
let topStudents = students.filter(student =>
  student.grade >= 85 && student.age < 21
);
console.log(topStudents);
// Çıxış: Ali, Leyla, Aynur

Praktik nümunə - axtarış funksiyası

filter() metodu axtarış və süzgəcləmə funksiyalarını yaratmaq üçün idealdır.

javascript
// Məhsul axtarış funksiyası
let products = [
  { name: 'Qırmızı köynək', price: 50, inStock: true },
  { name: 'Mavi şalvar', price: 80, inStock: false },
  { name: 'Qırmızı papaq', price: 30, inStock: true },
  { name: 'Yaşıl köynək', price: 45, inStock: true }
];

function searchProducts(items, searchTerm, maxPrice) {
  return items.filter(item =>
    item.name.toLowerCase().includes(searchTerm.toLowerCase()) &&
    item.price <= maxPrice &&
    item.inStock
  );
}

let results = searchProducts(products, 'qırmızı', 50);
console.log(results);
// Çıxış: [{ name: 'Qırmızı köynək', ...}, { name: 'Qırmızı papaq', ... }]
Məsləhətfilter() metodu boş massiv qaytara bilər - heç bir element şərtə uyğun gəlməzsə. Bu normal haldır və səhv deyil.

04 find() və findIndex() - elementləri tapmaq

find() və findIndex() metodları şərtə uyğun ilk elementi tapmaq üçün istifadə olunur. filter() metodundan fərqli olaraq, onlar yalnız ilk uyğun elementi qaytarırlar və sonra dayanırlar.

find() metodu

find() metodu şərtə uyğun gələn ilk elementi qaytarır. Heç bir element tapılmazsa undefined qaytarır.

javascript
let users = [
  { id: 1, name: 'Ali', role: 'user' },
  { id: 2, name: 'Leyla', role: 'admin' },
  { id: 3, name: 'Vəli', role: 'user' }
];

// Şərtə uyğun ilk elementi tapmaq
let admin = users.find(user => user.role === 'admin');
console.log(admin);
// Çıxış: { id: 2, name: 'Leyla', role: 'admin' }

// ID-yə görə istifadəçi tapmaq
let user = users.find(user => user.id === 3);
console.log(user);
// Çıxış: { id: 3, name: 'Vəli', role: 'user' }

// Element tapılmadı
let moderator = users.find(user => user.role === 'moderator');
console.log(moderator);
// Çıxış: undefined

findIndex() metodu

findIndex() metodu şərtə uyğun gələn ilk elementin indeksini qaytarır. Heç bir element tapılmazsa -1 qaytarır.

javascript
let numbers = [10, 20, 30, 40, 50];

// 25-dən böyük ilk ədədin indeksini tapmaq
let index = numbers.findIndex(num => num > 25);
console.log(index);       // Çıxış: 2 (30 indeksi)

// Element tapılmadı (-1)
let notFound = numbers.findIndex(num => num > 100);
console.log(notFound);    // Çıxış: -1

// Praktik nümunə - tapşırıqlar
let tasks = [
  { id: 1, title: 'Tapşırıq 1', completed: true },
  { id: 2, title: 'Tapşırıq 2', completed: false },
  { id: 3, title: 'Tapşırıq 3', completed: false }
];

let firstIncompleteIndex = tasks.findIndex(task => !task.completed);
console.log(firstIncompleteIndex);  // Çıxış: 1

Fərqlər

  • find(): Şərtə uyğun ilk elementi qaytarır (və ya undefined)
  • findIndex(): Şərtə uyğun ilk elementin indeksini qaytarır (və ya -1)
  • filter(): Şərtə uyğun bütün elementləri qaytarır (massiv)

05 some() və every() - şərtləri yoxlamaq

some() və every() metodları massivin elementləri haqqında boolean cavab verən suallar vermək üçün istifadə olunur. Onlar massivi dəyişdirmir və yalnız true və ya false qaytarırlar.

some() - ən azı bir element uyğun gəlirmi?

some() metodu massivin ən azı bir elementinin şərtə uyğun olub-olmadığını yoxlayır. Uyğun element tapıldıqda dərhal true qaytarır və dayanır.

javascript
let numbers = [1, 3, 5, 7, 9];

// Cüt ədəd varmı?
let hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven);     // Çıxış: false

// 5-dən böyük ədəd varmı?
let hasLarge = numbers.some(num => num > 5);
console.log(hasLarge);    // Çıxış: true

// Praktik nümunə - yaş yoxlaması
let users = [
  { name: 'Ali', age: 17 },
  { name: 'Leyla', age: 22 },
  { name: 'Vəli', age: 19 }
];

let hasAdult = users.some(user => user.age >= 18);
console.log(hasAdult);    // Çıxış: true
Performans qeydisome() metodu şərtə uyğun ilk elementi tapan kimi dayanır və qalan elementlərə baxmır. Bu onu böyük massivlər üçün effektiv edir.

every() - bütün elementlər uyğun gəlirmi?

every() metodu massivin bütün elementlərinin şərtə uyğun olub-olmadığını yoxlayır. İlk uyğun gəlməyən element tapıldıqda dərhal false qaytarır və dayanır.

javascript
let numbers = [2, 4, 6, 8, 10];

// Hamısı cüt ədəddir?
let allEven = numbers.every(num => num % 2 === 0);
console.log(allEven);     // Çıxış: true

// Hamısı müsbətdir?
let allPositive = numbers.every(num => num > 0);
console.log(allPositive); // Çıxış: true

// Praktik nümunə - bal yoxlaması
let scores = [85, 90, 78, 92, 88];

let allPassed = scores.every(score => score >= 60);
console.log(allPassed);   // Çıxış: true

let allExcellent = scores.every(score => score >= 90);
console.log(allExcellent);// Çıxış: false
Performans qeydievery() metodu şərtə uyğun gəlməyən ilk elementi tapan kimi dayanır. Bütün elementlər şərtə uyğun gəldikdə isə hamısını yoxlamalı olur.

Praktik nümunə - forma validasiyası

some() və every() metodları validasiya və yoxlama funksiyalarında çox faydalıdır.

javascript
// Forma validasiya funksiyası
function validateForm(formData) {
  let fields = [
    { name: 'ad', value: formData.name, required: true },
    { name: 'email', value: formData.email, required: true },
    { name: 'telefon', value: formData.phone, required: false }
  ];

  // Bütün məcburi sahələr doldurulubmu?
  let requiredFields = fields.filter(field => field.required);
  let allFilled = requiredFields.every(field => field.value && field.value.trim() !== '');

  // Boş məcburi sahə varmı?
  let hasEmpty = requiredFields.some(field => !field.value || field.value.trim() === '');

  return {
    isValid: allFilled,
    hasEmptyRequired: hasEmpty
  };
}

let result1 = validateForm({ name: 'Ali', email: 'ali@example.com', phone: '' });
console.log(result1);  // Çıxış: { isValid: true, hasEmptyRequired: false }

let result2 = validateForm({ name: 'Ali', email: '', phone: '123456' });
console.log(result2);  // Çıxış: { isValid: false, hasEmptyRequired: true }

06 Metod zəncirlərini istifadə etmək

Massiv metodları bir-birinin ardınca çağırıla bilər (zəncirlənə bilər). Bu, mürəkkəb məlumat transformasiyalarını aydın və oxunaqlı şəkildə yazmağa imkan verir.

Əsas zəncirləmə

Bir neçə metodu ardıcıl çağıraraq mürəkkəb əməliyyatlar yerinə yetirə bilərsiniz.

javascript
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Metodları zəncirləmək
let result = numbers
  .filter(num => num % 2 === 0)    // Yalnız cüt ədədləri saxla
  .map(num => num * 2);             // Hər birini 2-yə vur

console.log(result);  // Çıxış: [4, 8, 12, 16, 20]

// Addım-addım göstəriş
let step1 = numbers.filter(num => num % 2 === 0);
console.log(step1);   // Çıxış: [2, 4, 6, 8, 10]

let step2 = step1.map(num => num * 2);
console.log(step2);   // Çıxış: [4, 8, 12, 16, 20]

Mürəkkəb zəncirləmə

Real layihələrdə bir neçə filtrasiya və transformasiya əməliyyatını birləşdirə bilərsiniz.

javascript
let products = [
  { name: 'Laptop', price: 1000, category: 'elektronika', inStock: true },
  { name: 'Telefon', price: 500, category: 'elektronika', inStock: true },
  { name: 'Stol', price: 200, category: 'mebel', inStock: false },
  { name: 'Monitor', price: 300, category: 'elektronika', inStock: true },
  { name: 'Klaviatura', price: 50, category: 'elektronika', inStock: true }
];

// Mürəkkəb zəncir nümunəsi
let discountedElectronics = products
  .filter(p => p.category === 'elektronika')    // Yalnız elektronika
  .filter(p => p.inStock)                       // Yalnız stokda olanlar
  .map(p => ({                                  // 10% endirim əlavə et
    name: p.name,
    oldPrice: p.price,
    newPrice: p.price * 0.9,
    savings: p.price * 0.1
  }))
  .filter(p => p.oldPrice > 100);               // Yalnız 100-dən bahalılar

console.log(discountedElectronics);
// Çıxış:
// [
//   { name: 'Laptop', oldPrice: 1000, newPrice: 900, savings: 100 },
//   { name: 'Telefon', oldPrice: 500, newPrice: 450, savings: 50 },
//   { name: 'Monitor', oldPrice: 300, newPrice: 270, savings: 30 }
// ]

Ən yaxşı təcrübələr

  • Filtrasiya əməliyyatlarını əvvəl edin - bu, sonrakı əməliyyatlarda işlənəcək element sayını azaldır
  • Hər metodu ayrı sətirdə yazın - kodu daha oxunaqlı edir
  • Çox mürəkkəb zəncirləri ara dəyişənlərə bölün - debug etmək asanlaşır
  • Hər addımda nə baş verdiyini düşünün - hər metod yeni massiv qaytarır

07 Performans optimizasiyası

Funksional massiv metodları rahat və oxunaqlıdır, lakin onların performans xüsusiyyətlərini başa düşmək vacibdir. Böyük massivlərlə işləyərkən optimizasiya vacib ola bilər.

Vaxt mürəkkəbliyi

  • map() - O(n) - bütün elementləri emal edir
  • filter() - O(n) - bütün elementləri yoxlayır
  • find() - O(n) ən pis halda, lakin tapılan kimi dayanır
  • some() - O(n) ən pis halda, lakin tapılan kimi dayanır
  • every() - O(n) ən pis halda, lakin uyğun gəlməyən tapılan kimi dayanır

Optimallaşdırma məsləhətləri

Zəncirlərdə əməliyyatların sırasını düşünərək performansı yaxşılaşdıra bilərsiniz.

javascript
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// ❌ Səmərəsiz yol
let result1 = numbers
  .map(num => num * 2)           // Bütün elementləri iki dəfə artır
  .filter(num => num > 10);      // Sonra filtrləyir

// ✅ Səmərəli yol
let result2 = numbers
  .filter(num => num > 5)        // Əvvəlcə filtrləyir
  .map(num => num * 2);          // Sonra iki dəfə artırır

console.log(result1);  // Çıxış: [12, 14, 16, 18, 20]
console.log(result2);  // Çıxış: [12, 14, 16, 18, 20]

// Performans fərqi
// result1: 10 map əməliyyatı + 10 filter əməliyyatı = 20 əməliyyat
// result2: 10 filter əməliyyatı + 5 map əməliyyatı = 15 əməliyyat

Nə vaxt adi dövrlərdən istifadə etmək olar

Bəzi hallarda adi for dövrü funksional metodlardan daha effektiv ola bilər:

  • Erkən çıxış lazım olduqda (break istifadə edərək)
  • Bir keçiddə bir neçə əməliyyat etmək lazım olduqda
  • Çox böyük massivlərdə və kritik performans tələb olunduqda
BalansƏksər hallarda oxunaqlılıq performansdan daha vacibdir. Performans problemi olmadıqca funksional metodları istifadə edin.

Xülasə

map() metodu hər bir elementi transformasiya edərək yeni massiv yaradır
filter() metodu şərtə uyğun elementləri seçərək yeni massiv qaytarır
find() və findIndex() şərtə uyğun ilk elementi və ya indeksini tapır
some() ən azı bir elementin şərtə uyğun olub-olmadığını, every() isə bütün elementlərin uyğun olub-olmadığını yoxlayır
Metod zəncirlərini istifadə edərək mürəkkəb məlumat transformasiyalarını aydın şəkildə yaza bilərik
Performans optimizasiyası üçün filtrasiya əməliyyatlarını əvvəl etmək və zəncirlərin sırasını düşünmək vacibdir

Təklifiniz var, səhv və ya xəta tapdınız? Zəhmət olmasa bizimlə əlaqə saxlayın.