Arrays — Core to Advanced Operations
"The Backbone of Data Structures"
জাভাস্ক্রিপ্ট ডেভেলপমেন্টে তুমি যদি React, Node.js বা বড় কোনো সিস্টেম নিয়ে কাজ করো, তোমার ৯০% সময় কাটবে Array এর সাথে মারামারি করে। ডেটা আনা, ফিল্টার করা, সাজানো এবং ইউজারের সামনে প্রেজেন্ট করা—সবই অ্যারের খেলা।
এই অধ্যায়ে আমরা শুধু মেথড শিখব না, শিখব Performance এবং Immutability।
১. Array আসলে কী? (Under the Hood)
সহজ কথায়, Array হলো একটি Ordered Collection। কিন্তু ইঞ্জিনের ভেতরে, জাভাস্ক্রিপ্ট অ্যারে আসলে এক ধরণের বিশেষ Object, যেখানে Key গুলো হলো ইনডেক্স (0, 1, 2...)।
const numbers = [10, 20, 30];
// মেমোরিতে এটা অনেকটা এমন: { 0: 10, 1: 20, 2: 30, length: 3 }
Basic CRUD Operations
- Add (End): push(40) — Fastest 🚀 (কারণ ইনডেক্স বদলাতে হয় না)
- Add (Start): unshift(5) — Slow 🐢 (কারণ সব এলিমেন্টকে ১ ঘর করে ডানে সরাতে হয়)
- Remove (End): pop() — Fastest
- Remove (Start): shift() — Slow
Senior Tip:
বড় ডেটাসেটের ক্ষেত্রে unshift বা shift ব্যবহার এড়িয়ে চলো, কারণ এটি রি-ইনডেক্সিং এর কারণে পারফরম্যান্স ড্রপ করে।
২. The "Holy Trinity": Map, Filter, Reduce
মডার্ন জাভাস্ক্রিপ্ট (বিশেষ করে React) দাঁড়িয়ে আছে এই তিনটি পিলারের ওপর। লুপ চালানোর চেয়ে এগুলো ব্যবহার করা অনেক বেশি ক্লিন এবং রিডেবল।
A) map() — The Transformer 🤖
ইনপুট অ্যারের প্রতিটি উপাদানকে বদলে নতুন একটি অ্যারে তৈরি করে। Length: ইনপুট যা, আউটপুটও তা।
const prices = [10, 20, 30];
const taxAdded = prices.map(price => price * 1.15); // 15% Tax
console.log(taxAdded); // [11.5, 23, 34.5]
B) filter() — The Gatekeeper 🛡️
শর্ত মিললে রাখবে, না মিললে বাদ দেবে। Length: ইনপুটের সমান বা কম হবে।
const products = [
{ name: "Mobile", price: 10000 },
{ name: "Laptop", price: 50000 },
{ name: "Watch", price: 3000 }
];
// ৫০০০ টাকার ওপরের প্রোডাক্টগুলো দাও
const expensive = products.filter(p => p.price > 5000);
C) reduce() — The Swiss Army Knife 🛠️
এটি সবচেয়ে পাওয়ারফুল। অনেকগুলো ভ্যালুকে একটিতে রূপান্তর করে (যেমন: যোগফল, অবজেক্ট তৈরি, বা গ্রুপিং)।
const cart = [100, 200, 300];
// acc = Accumulator (জমার খাতা), cur = Current Value
const total = cart.reduce((acc, cur) => acc + cur, 0);
console.log(total); // 600
এখানে 0 হলো ইনিশিয়াল ভ্যালু। প্রথমে acc এর মান 0, তারপর 0+100, তারপর 100+200... এভাবে চলে।
৩. Finding & Checking (খোঁজ দ্য সার্চ)
লুপ চালিয়ে খোঁজার দিন শেষ।
find():
প্রথম যেটা মিলবে, শুধু সেটা দেবে।
const user = users.find(u => u.id === 55); // Returns Object or undefined
some():
অন্তত একজন কি শর্ত মানে? (Return true/false)
const hasAdmin = users.some(u => u.role === 'admin');
every():
সবাই কি শর্ত মানে?
const allAdults = users.every(u => u.age >= 18);
⭐ ৪. Mutation: The Danger Zone ⚠️
সিনিয়র ডেভেলপাররা সবসময় Immutability পছন্দ করেন। অর্থাৎ অরিজিনাল অ্যারে চেঞ্জ না করে কপি নিয়ে কাজ করা।
❌ Mutating Methods
(Original Array নষ্ট করে দেয়)
- push, pop, shift, unshift
- splice (Remove/Insert)
- sort, reverse
✅ Immutable Methods
(New Array রিটার্ন করে)
- map, filter, reduce
- slice (Copy create করে)
- toSorted() (Modern JS - 2023)
The sort() Trap
জাভাস্ক্রিপ্টে sort() বাই-ডিফল্ট সংখ্যাকে স্ট্রিং হিসেবে চিন্তা করে সর্ট করে!
const nums = [2, 10, 50, 1];
nums.sort();
console.log(nums); // [1, 10, 2, 50] 😲 ভুল!
// Correct Way for Numbers:
nums.sort((a, b) => a - b); // Ascending
⭐ ৫. Copying Arrays: Shallow vs Deep (Interview Favourite)
অ্যারে একটি Reference Type। তাই a = b লিখলে কপি হয় না, লিংক তৈরি হয়।
const original = [1, 2];
const copy = original;
copy.push(3);
console.log(original); // [1, 2, 3] 😱 অরিজিনালটাও বদলে গেছে!
✔ Shallow Copy (উপরের লেভেল কপি)
const safeCopy = [...original]; // Spread operator
// অথবা
const safeCopy2 = original.slice();
সমস্যা: যদি অ্যারের ভেতরে আরেকটা অ্যারে (Nested) থাকে, তবে ভেতরেরটা ঠিকমতো কপি হয় না (Reference থেকে যায়)।
✔ Deep Copy (একদম নতুন কপি)
// Old Hack (Slow & Data Loss risk for functions/dates)
const deep = JSON.parse(JSON.stringify(original));
// ✅ Modern Best Practice (Fast & Safe)
const deepPerfect = structuredClone(original);
⭐ ৬. Senior Level Problem Solving Patterns
নিচের প্যাটার্নগুলো মুখস্থ না করে বোঝার চেষ্টা করো, এগুলো রিয়েল লাইফে প্রচুর কাজে লাগে।
🔥 ১. ডুপ্লিকেট রিমুভ করা (One Liner)
const ids = [1, 2, 2, 3, 4, 4, 5];
const uniqueIds = [...new Set(ids)];
console.log(uniqueIds); // [1, 2, 3, 4, 5]
🔥 ২. অ্যারে থেকে অবজেক্ট বানানো (Data Transformation)
const users = [ {id: 1, name: 'A'}, {id: 2, name: 'B'} ];
// আমরা চাই: { 1: 'A', 2: 'B' } যাতে সহজে খোঁজা যায়
const userMap = users.reduce((acc, user) => {
acc[user.id] = user.name;
return acc;
}, {});
🔥 ৩. কন্ডিশনালি আইটেম আপডেট করা (React Style)
// অরিজিনাল অ্যারে টাচ না করে ID 2 এর নাম বদলাও
const updatedUsers = users.map(user =>
user.id === 2 ? { ...user, name: "New Name" } : user
);
⭐ ৭. Performance & Best Practices
map vs forEach:
যদি তোমার নতুন অ্যারে দরকার হয় তবেই map ব্যবহার করো। শুধু লুপ ঘোরার জন্য forEach বা for...of ব্যবহার করো। map মেমোরি এলোকেট করে, তাই শুধু লুপের জন্য map ব্যবহার করা অপচয়।
Chaining:
arr.filter(...).map(...) খুব ক্লিন কোড, কিন্তু বড় অ্যারের জন্য এটি দুইবার লুপ চালায়। পারফরম্যান্স ক্রিটিক্যাল হলে reduce দিয়ে একবারে করা ভালো।
Flat:
নেস্টেড অ্যারে সোজা করতে arr.flat(Infinity) জাদুর মতো কাজ করে।
🚀 অধ্যায় ৫ সারাংশ (Checklist)
আমরা শিখলাম:
- ✓ Basics: push/pop ফাস্ট, shift/unshift স্লো
- ✓ Functional: map, filter, reduce দিয়ে ইমিউটেবল কোড লেখা
- ✓ Search: find এবং some এর ব্যবহার
- ✓ Traps: sort() এর ডিফল্ট বিহেভভিয়ার এবং splice vs slice
- ✓ Copy: structuredClone দিয়ে সেফ ডিপ কপি
- ✓ Logic: Set দিয়ে ডুপ্লিকেট রিমুভ এবং reduce দিয়ে অবজেক্ট বানানো
Next Step: অ্যারে তো হলো, কিন্তু রিয়েল ওয়ার্ল্ড ডেটা থাকে Objects-এ। পরের অধ্যায়ে আমরা অবজেক্টের গভীরে ডুব দেব, যেখানে this কিওয়ার্ড, Prototypes, এবং Descriptors অপেক্ষা করছে।