01 reduce() metoduna giriş
reduce() metodu JavaScript-də ən güclü massiv metodlarından biridir. O, massivin bütün elementlərini tək bir nəticəyə (ədəd, mətn, obyekt və ya massiv) çevirir. Bu metod hər addımda əvvəlki nəticəni növbəti elementlə birləşdirir.
Əsas nümunə
reduce() metodunun ən sadə istifadəsi ədədləri toplamaq və ya digər sadə aqreqasiya əməliyyatları yerinə yetirməkdir.
// Sadə cəm hesablama
let numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
}, 0);
console.log(sum); // Çıxış: 15
// Qısa yazılış forması
let sum2 = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum2); // Çıxış: 15Sintaksis və parametrlər
reduce() metodu callback funksiyası və istəyə bağlı başlanğıc dəyər qəbul edir.
array.reduce((accumulator, currentValue, currentIndex, array) => {
// Burada əməliyyat məntiqi gedir
return accumulator;
}, initialValue);Callback funksiyasının parametrləri
accumulator- Yığıcı (akkumulyator) - əvvəlki callback çağırışının nəticəsi və ya başlanğıc dəyərcurrentValue- Cari element - hal-hazırda emal olunan massiv elementicurrentIndex- Cari indeks - cari elementin mövqeyi (istəyə bağlı)array- Əsas massiv - reduce() çağırılan massiv (istəyə bağlı)initialValue- Başlanğıc dəyər - ilk callback çağırışında akkumulyatorun dəyəri (istəyə bağlı)
Necə işləyir?
reduce() metodu massivin hər elementini növbə ilə emal edir və hər addımda akkumulyatoru yeniləyir.
let numbers = [1, 2, 3, 4];
let sum = numbers.reduce((acc, curr) => {
console.log(`Accumulator: ${acc}, Current: ${curr}`);
return acc + curr;
}, 0);
// Çıxış:
// Accumulator: 0, Current: 1 -> qaytarır 1
// Accumulator: 1, Current: 2 -> qaytarır 3
// Accumulator: 3, Current: 3 -> qaytarır 6
// Accumulator: 6, Current: 4 -> qaytarır 10
console.log(sum); // Çıxış: 10Başlanğıc dəyər ilə və olmadan
reduce() metoduna başlanğıc dəyər vermək və ya verməmək müxtəlif nəticələrə səbəb ola bilər.
let numbers = [1, 2, 3, 4];
// Başlanğıc dəyər ilə (0)
let sum1 = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum1); // Çıxış: 10
// Başlanğıc dəyər olmadan
let sum2 = numbers.reduce((acc, curr) => acc + curr);
console.log(sum2); // Çıxış: 10
// ⚠️ Boş massiv halında səhv
let empty = [];
// let result = empty.reduce((acc, curr) => acc + curr); // TypeError: Reduce of empty array with no initial value
let safeResult = empty.reduce((acc, curr) => acc + curr, 0);
console.log(safeResult); // Çıxış: 0
// Tək elementli massivdə
let single = [5];
let result1 = single.reduce((acc, curr) => acc + curr);
console.log(result1); // Çıxış: 5 (callback çağırılmır)02 Geniş istifadə olunan nümunələr
reduce() metodu müxtəlif aqreqasiya əməliyyatları üçün istifadə oluna bilər. Gəlin ən çox istifadə olunan nümunələrə baxaq.
Cəm və orta hesablama
reduce() ilə ədədlərin cəmini və orta qiymətini hesablamaq çox sadədir.
let scores = [85, 90, 78, 92, 88, 95];
// Ümumi bal
let totalScore = scores.reduce((sum, score) => sum + score, 0);
console.log(totalScore); // Çıxış: 528
// Orta qiymət
let average = scores.reduce((sum, score, index, array) => {
sum += score;
if (index === array.length - 1) {
return sum / array.length;
}
return sum;
}, 0);
console.log(average); // Çıxış: 88
// Daha sadə yolla orta qiymət
let avg = scores.reduce((sum, score) => sum + score, 0) / scores.length;
console.log(avg); // Çıxış: 88Maksimum və minimum tapmaq
reduce() ilə massivin ən böyük və ya ən kiçik elementini tapa bilərik.
let numbers = [45, 23, 67, 12, 89, 34];
// Ən böyük elementi tapmaq
let max = numbers.reduce((maximum, current) => {
return current > maximum ? current : maximum;
});
console.log(max); // Çıxış: 89
// Ən kiçik elementi tapmaq
let min = numbers.reduce((minimum, current) => {
return current < minimum ? current : minimum;
});
console.log(min); // Çıxış: 12
// Obyekt xüsusiyyətinə görə
let products = [
{ name: 'Laptop', price: 1000 },
{ name: 'Telefon', price: 500 },
{ name: 'Monitor', price: 300 }
];
let mostExpensive = products.reduce((max, product) => {
return product.price > max.price ? product : max;
});
console.log(mostExpensive); // Çıxış: { name: 'Laptop', price: 1000 }Elementləri saymaq
reduce() ilə hər elementin neçə dəfə təkrarlandığını və ya müəyyən şərtə uyğun elementləri saya bilərik.
// Hər elementin sayını saymaq
let fruits = ['alma', 'armud', 'alma', 'banan', 'armud', 'alma', 'gilas'];
let fruitCount = fruits.reduce((count, fruit) => {
count[fruit] = (count[fruit] || 0) + 1;
return count;
}, {});
console.log(fruitCount);
// Çıxış: { alma: 3, armud: 2, banan: 1, gilas: 1 }
// Şərtə uyğun elementləri saymaq
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let evenCount = numbers.reduce((count, num) => {
return num % 2 === 0 ? count + 1 : count;
}, 0);
console.log(evenCount); // Çıxış: 5İç-içə massivləri açmaq
reduce() ilə iç-içə massivləri bir səviyyəyə çevirə bilərik.
// İç-içə massivi açmaq
let nested = [[1, 2], [3, 4], [5, 6]];
let flattened = nested.reduce((flat, current) => {
return flat.concat(current);
}, []);
console.log(flattened); // Çıxış: [1, 2, 3, 4, 5, 6]
// Spread operatoru ilə
let flattened2 = nested.reduce((flat, current) => [...flat, ...current], []);
console.log(flattened2); // Çıxış: [1, 2, 3, 4, 5, 6]
// Mürəkkəb açma - obyekt içindəki massivlər
let data = [
{ tags: ['js', 'web'] },
{ tags: ['python', 'data'] },
{ tags: ['js', 'node'] }
];
let allTags = data.reduce((tags, item) => tags.concat(item.tags), []);
console.log(allTags); // Çıxış: ['js', 'web', 'python', 'data', 'js', 'node']03 Qabaqcıl patternlər
reduce() metodunun əsl gücü mürəkkəb məlumat transformasiyalarında ortaya çıxır. Bu bölmədə qabaqcıl istifadə patternlərini öyrənəcəyik.
Qruplaşdırma
reduce() ilə massiv elementlərini müəyyən xüsusiyyətə görə qruplaşdıra bilərik.
// Xüsusiyyətə görə qruplaşdırmaq
let students = [
{ name: 'Ali', group: 'A', grade: 85 },
{ name: 'Leyla', group: 'B', grade: 92 },
{ name: 'Vəli', group: 'A', grade: 78 },
{ name: 'Aynur', group: 'B', grade: 88 },
{ name: 'Rəşad', group: 'A', grade: 91 }
];
let byGroup = students.reduce((grouped, student) => {
let group = student.group;
if (!grouped[group]) {
grouped[group] = [];
}
grouped[group].push(student);
return grouped;
}, {});
console.log(byGroup);
// Çıxış:
// {
// A: [
// { name: 'Ali', group: 'A', grade: 85 },
// { name: 'Vəli', group: 'A', grade: 78 },
// { name: 'Rəşad', group: 'A', grade: 91 }
// ],
// B: [
// { name: 'Leyla', group: 'B', grade: 92 },
// { name: 'Aynur', group: 'B', grade: 88 }
// ]
// }
// Şərtə görə qruplaşdırmaq
let byPerformance = students.reduce((grouped, student) => {
let category = student.grade >= 85 ? 'yüksək' : 'orta';
if (!grouped[category]) {
grouped[category] = [];
}
grouped[category].push(student.name);
return grouped;
}, {});
console.log(byPerformance);
// Çıxış: { yüksək: ['Ali', 'Leyla', 'Aynur', 'Rəşad'], orta: ['Vəli'] }Obyekt transformasiyası
Massivi obyektə çevirmək - tez-tez istifadə olunan patternlərdən biridir.
// Massivi obyektə çevirmək
let users = [
{ id: 1, name: 'Ali', email: 'ali@example.com' },
{ id: 2, name: 'Leyla', email: 'leyla@example.com' },
{ id: 3, name: 'Vəli', email: 'veli@example.com' }
];
let usersById = users.reduce((obj, user) => {
obj[user.id] = user;
return obj;
}, {});
console.log(usersById);
// Çıxış:
// {
// '1': { id: 1, name: 'Ali', email: 'ali@example.com' },
// '2': { id: 2, name: 'Leyla', email: 'leyla@example.com' },
// '3': { id: 3, name: 'Vəli', email: 'veli@example.com' }
// }
// Xüsusiyyətləri çıxarmaq
let userEmails = users.reduce((obj, user) => {
obj[user.name] = user.email;
return obj;
}, {});
console.log(userEmails);
// Çıxış: { Ali: 'ali@example.com', Leyla: 'leyla@example.com', Vəli: 'veli@example.com' }Dublikatları silmək
reduce() ilə massivdən təkrarlanan elementləri çıxara bilərik.
// Dublikatları silmək
let numbers = [1, 2, 3, 2, 4, 3, 5, 1, 6];
let unique = numbers.reduce((acc, current) => {
if (!acc.includes(current)) {
acc.push(current);
}
return acc;
}, []);
console.log(unique); // Çıxış: [1, 2, 3, 4, 5, 6]
// Obyektlərdə dublikatları silmək
let products = [
{ id: 1, name: 'Laptop' },
{ id: 2, name: 'Telefon' },
{ id: 1, name: 'Laptop' },
{ id: 3, name: 'Monitor' }
];
let uniqueProducts = products.reduce((acc, product) => {
if (!acc.find(p => p.id === product.id)) {
acc.push(product);
}
return acc;
}, []);
console.log(uniqueProducts);
// Çıxış: [{ id: 1, name: 'Laptop' }, { id: 2, name: 'Telefon' }, { id: 3, name: 'Monitor' }]Bir keçiddə bir neçə əməliyyat
reduce() ilə bir neçə əməliyyatı tək bir keçiddə yerinə yetirərək performansı artıra bilərik.
// Bir keçiddə çoxlu əməliyyat
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Bir neçə zəncirlənmiş metod - 3 keçid
let result1 = numbers
.filter(n => n % 2 === 0)
.map(n => n * 2)
.reduce((sum, n) => sum + n, 0);
// Tək reduce - 1 keçid
let result2 = numbers.reduce((sum, n) => {
if (n % 2 === 0) {
return sum + (n * 2);
}
return sum;
}, 0);
console.log(result1); // Çıxış: 60
console.log(result2); // Çıxış: 6004 reduceRight() metodu
reduceRight() metodu reduce() ilə eynidir, lakin massivi sağdan-sola (sondan-əvvələ) emal edir. Bu bəzi xüsusi hallarda faydalıdır.
Əsas istifadə
reduceRight() massivin son elementindən başlayaraq əməliyyatı yerinə yetirir.
let numbers = [1, 2, 3, 4, 5];
// reduce() - soldan-sağa
let result1 = numbers.reduce((acc, curr) => {
console.log(`${acc} + ${curr}`);
return acc + curr;
});
// Çıxış: 1 + 2, 3 + 3, 6 + 4, 10 + 5
// reduceRight() - sağdan-sola
let result2 = numbers.reduceRight((acc, curr) => {
console.log(`${acc} + ${curr}`);
return acc + curr;
});
// Çıxış: 5 + 4, 9 + 3, 12 + 2, 14 + 1
console.log(result1); // Çıxış: 15
console.log(result2); // Çıxış: 15İstifadə halları
reduceRight() xüsusilə funksiya kompozisiyası və sağdan-sola ardıcıllıq tələb edən əməliyyatlarda faydalıdır.
// Mətn elementlərini tərsinə çevirmək
let words = ['Salam', 'dünya', 'JavaScript'];
let reversed = words.reduceRight((result, word) => result + ' ' + word, '');
console.log(reversed); // Çıxış: ' JavaScript dünya Salam'
// Funksiya kompozisiyası
let functions = [
x => x + 1,
x => x * 2,
x => x - 3
];
// Soldan-sağa icra
let compose = functions.reduce((acc, fn) => {
return (x) => fn(acc(x));
});
// Sağdan-sola icra
let composeRight = functions.reduceRight((acc, fn) => {
return (x) => fn(acc(x));
});
console.log(compose(5)); // Çıxış: ((5 + 1) * 2) - 3 = 9
console.log(composeRight(5)); // Çıxış: ((5 - 3) * 2) + 1 = 5reduce() və reduceRight() arasında fərq
- reduce(): Massivi soldan-sağa (əvvəldən-sona) emal edir
- reduceRight(): Massivi sağdan-sola (sondan-əvvələ) emal edir
05 Kompozisiya və mürəkkəb transformasiyalar
reduce() metodu digər massiv metodları ilə birlikdə funksiya kompozisiyası üçün güclü alətdir.
Digər metodlarla birləşdirmək
reduce() metodunu filter() və map() ilə birləşdirərək mürəkkəb məlumat analizi edə bilərik.
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 }
];
// filter, map və reduce birlikdə
let result = products
.filter(p => p.category === 'elektronika')
.filter(p => p.inStock)
.reduce((total, p) => total + p.price, 0);
console.log(result); // Çıxış: 1850
// Mürəkkəb statistika toplamaq
let stats = products.reduce((acc, product) => {
acc.total++;
acc.inStock += product.inStock ? 1 : 0;
acc.totalValue += product.price;
if (product.category === 'elektronika') {
acc.electronics++;
}
return acc;
}, {
total: 0,
inStock: 0,
totalValue: 0,
electronics: 0
});
console.log(stats);
// Çıxış: { total: 5, inStock: 4, totalValue: 2050, electronics: 4 }Mürəkkəb məlumat strukturları qurmaq
reduce() ilə çox səviyyəli iç-içə obyektlər və mürəkkəb məlumat strukturları yarada bilərik.
// İç-içə məlumat strukturu qurmaq
let transactions = [
{ date: '2024-01-15', category: 'yemək', amount: 50 },
{ date: '2024-01-16', category: 'nəqliyyat', amount: 30 },
{ date: '2024-01-15', category: 'yemək', amount: 25 },
{ date: '2024-02-10', category: 'yemək', amount: 40 },
{ date: '2024-02-11', category: 'nəqliyyat', amount: 20 }
];
let summary = transactions.reduce((acc, transaction) => {
let [year, month] = transaction.date.split('-');
let monthKey = `${year}-${month}`;
if (!acc[monthKey]) {
acc[monthKey] = {};
}
if (!acc[monthKey][transaction.category]) {
acc[monthKey][transaction.category] = 0;
}
acc[monthKey][transaction.category] += transaction.amount;
return acc;
}, {});
console.log(summary);
// Çıxış:
// {
// '2024-01': { yemək: 75, nəqliyyat: 30 },
// '2024-02': { yemək: 40, nəqliyyat: 20 }
// }Funksiya kompozisiyası
reduce() ilə funksiyaları birləşdirərək güclü pipeline-lar yarada bilərik.
// Funksiya kompozisiya funksiyaları
let pipe = (...functions) => {
return (initialValue) => {
return functions.reduce((value, fn) => fn(value), initialValue);
};
};
let compose = (...functions) => {
return (initialValue) => {
return functions.reduceRight((value, fn) => fn(value), initialValue);
};
};
// Köməkçi funksiyalar
let add5 = x => x + 5;
let multiply3 = x => x * 3;
let subtract2 = x => x - 2;
// pipe: Soldan-sağa icra
let pipeline = pipe(add5, multiply3, subtract2);
console.log(pipeline(10)); // Çıxış: ((10 + 5) * 3) - 2 = 43
// compose: Sağdan-sola icra
let composition = compose(add5, multiply3, subtract2);
console.log(composition(10)); // Çıxış: ((10 - 2) * 3) + 5 = 2906 Performans və ən yaxşı təcrübələr
reduce() güclü metoddur, lakin onu düzgün istifadə etmək vacibdir. Gəlin performans və kod keyfiyyəti məsələlərinə baxaq.
Performans nəzərə alınmaları
reduce() bəzən bir neçə zəncirli metod çağırışından daha sürətli ola bilər, çünki massivi yalnız bir dəfə keçir.
let largeArray = Array.from({ length: 10000 }, (_, i) => i + 1);
// ❌ Səmərəsiz - 3 keçid
console.time('Multiple passes');
let result1 = largeArray
.filter(n => n % 2 === 0)
.map(n => n * 2)
.reduce((sum, n) => sum + n, 0);
console.timeEnd('Multiple passes');
// ✅ Səmərəli - Bir keçiddə çoxlu əməliyyat
console.time('Single pass');
let result2 = largeArray.reduce((sum, n) => {
if (n % 2 === 0) {
return sum + (n * 2);
}
return sum;
}, 0);
console.timeEnd('Single pass');
console.log(result1 === result2); // Çıxış: true
// Qeyd: Böyük massivlərdə fərq daha aydın görünürPerformans məsləhətləri
- Bir keçiddə bir neçə əməliyyat etmək üçün reduce() istifadə edin
- Çox böyük massivlərdə metodları zəncirləmək əvəzinə reduce() istifadə etməyi düşünün
- Sadə əməliyyatlar üçün (məsələn, yalnız map) reduce() ilə həddən artıq mürəkkəbləşdirməyin
- Boş massivlərə qarşı həmişə başlanğıc dəyər istifadə edin
Oxunaqlılıq və performans balansı
Bəzən performans üçün optimallaşdırılmış kod oxunması çətin ola bilər. Balans tapmaq vacibdir.
let orders = [
{ id: 1, items: 3, total: 150 },
{ id: 2, items: 1, total: 50 },
{ id: 3, items: 5, total: 200 }
];
// ✅ Oxunaqlı - niyyət aydındır
let totalRevenue = orders
.map(order => order.total)
.reduce((sum, total) => sum + total, 0);
// ✅ Performant - daha sürətli, amma bir az daha az oxunaqlı
let totalRevenue2 = orders.reduce((sum, order) => sum + order.total, 0);
console.log(totalRevenue); // Çıxış: 400
console.log(totalRevenue2); // Çıxış: 400
// Tövsiyə
// - Kiçik massivlər üçün oxunaqlılıq vacibdir
// - Böyük massivlər və performans problemlərində optimallaşdırmağı düşününƏn yaxşı təcrübələr
- Həmişə başlanğıc dəyər verin (boş massivlər üçün xüsusilə vacibdir)
- Akkumulyatoru həmişə qaytarın - unutmaq ən çox görülən səhvdir
- Mürəkkəb callback-lər üçün ayrıca funksiya yazın
- Sadə əməliyyatlar üçün oxunaqlı variant seçin (map/filter)
- Performans problemi olmadıqca oxunaqlılığı performansdan üstün tutun
- reduce() çox mürəkkəkləşdikdə, ara dəyişənlər və ya adi dövrlərdən istifadə etməyi düşünün
Geniş yayılmış səhvlər
reduce() istifadə edərkən bəzi səhvlərdən qaçınmaq vacibdir.
// ❌ Səhv 1: return yazmağı unutmaq
let numbers = [1, 2, 3];
// let result = numbers.reduce((sum, n) => {
// sum + n; // return yoxdur!
// }, 0);
// console.log(result); // Çıxış: undefined
// ✅ Düzgün: return ilə
let result = numbers.reduce((sum, n) => {
return sum + n;
}, 0);
console.log(result); // Çıxış: 6
// ❌ Səhv 2: Boş massivdə başlanğıc dəyər verməmək
// let empty = [];
// let emptyResult = empty.reduce((sum, n) => sum + n); // TypeError: Reduce of empty array with no initial value
// ✅ Düzgün: başlanğıc dəyər ilə
let empty = [];
let emptyResult = empty.reduce((sum, n) => sum + n, 0);
console.log(emptyResult); // Çıxış: 0
// ❌ Səhv 3: Akkumulyatoru qaytarmamaq
let items = [{ value: 1 }, { value: 2 }, { value: 3 }];
// let wrongResult = items.reduce((acc, item) => {
// acc.push(item.value);
// // acc qaytarılmır!
// }, []);
// ✅ Düzgün: acc qaytarılır
let correctResult = items.reduce((acc, item) => {
acc.push(item.value);
return acc;
}, []);
console.log(correctResult); // Çıxış: [1, 2, 3]Xülasə
Təklifiniz var, səhv və ya xəta tapdınız? Zəhmət olmasa bizimlə əlaqə saxlayın.