π Array Methods
JavaScript provides powerful built-in methods for working with arrays. These methods allow you to transform, filter, search, and manipulate arrays in elegant and efficient ways. Mastering array methods is essential for modern JavaScript development.
Array methods can be mutating (modify the original array) or non-mutating (return a new array). Understanding the difference is crucial to avoid bugs.
π forEach() - Iterate Over Elements
forEach() executes a provided function once for each array element. It's the most basic iteration method.
// Basic syntax
array.forEach((element, index, array) => {
// Code to execute for each element
});
// Example: Logging each element
const fruits = ['apple', 'banana', 'orange'];
fruits.forEach((fruit) => {
console.log(fruit);
});
// Output:
// apple
// banana
// orange
// Example: Using index parameter
const numbers = [10, 20, 30];
numbers.forEach((num, index) => {
console.log(`Index ${index}: ${num}`);
});
// Output:
// Index 0: 10
// Index 1: 20
// Index 2: 30
// Example: Modifying external variable
let sum = 0;
const values = [1, 2, 3, 4, 5];
values.forEach((value) => {
sum += value;
});
console.log(sum); // 15
forEach() does not return a value (returns undefined). If you need to transform or filter an array, use map() or filter() instead.
πΊοΈ map() - Transform Elements
map() creates a new array by applying a function to each element. It's one of the most commonly used array methods.
// Basic syntax
const newArray = array.map((element, index, array) => {
return newValue;
});
// Example: Double each number
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5] (original unchanged)
// Example: Extract property from objects
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 }
];
const names = users.map((user) => user.name);
console.log(names); // ['Alice', 'Bob', 'Charlie']
// Example: Transform to different structure
const prices = [10, 20, 30];
const products = prices.map((price, index) => ({
id: index + 1,
price: price,
discounted: price * 0.9
}));
console.log(products);
// [
// { id: 1, price: 10, discounted: 9 },
// { id: 2, price: 20, discounted: 18 },
// { id: 3, price: 30, discounted: 27 }
// ]
// Example: Convert strings to uppercase
const words = ['hello', 'world', 'javascript'];
const uppercase = words.map((word) => word.toUpperCase());
console.log(uppercase); // ['HELLO', 'WORLD', 'JAVASCRIPT']
map() always returns an array with the same length as the original. If you need to filter out elements, use filter() or combine filter() and map().
π filter() - Select Elements
filter() creates a new array containing only elements that pass a test (return true from the callback function).
// Basic syntax
const newArray = array.filter((element, index, array) => {
return condition; // Return true to keep element, false to exclude
});
// Example: Filter even numbers
const numbers = [1, 2, 3, 4, 5, 6, 7, 8];
const evenNumbers = numbers.filter((num) => num % 2 === 0);
console.log(evenNumbers); // [2, 4, 6, 8]
// Example: Filter by property
const users = [
{ name: 'Alice', age: 25, active: true },
{ name: 'Bob', age: 17, active: false },
{ name: 'Charlie', age: 30, active: true },
{ name: 'David', age: 16, active: true }
];
const activeAdults = users.filter((user) => user.age >= 18 && user.active);
console.log(activeAdults);
// [
// { name: 'Alice', age: 25, active: true },
// { name: 'Charlie', age: 30, active: true }
// ]
// Example: Filter by string condition
const words = ['apple', 'banana', 'apricot', 'cherry', 'avocado'];
const aWords = words.filter((word) => word.startsWith('a'));
console.log(aWords); // ['apple', 'apricot', 'avocado']
// Example: Remove falsy values
const mixed = [0, 1, false, 2, '', 3, null, undefined, 4, NaN];
const truthy = mixed.filter(Boolean); // Shorthand for (val) => Boolean(val)
console.log(truthy); // [1, 2, 3, 4]
π reduce() - Accumulate Values
reduce() executes a reducer function on each element, resulting in a single output value. It's the most versatile array method.
// Basic syntax
const result = array.reduce((accumulator, currentValue, index, array) => {
return newAccumulator;
}, initialValue);
// Example: Sum all numbers
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((total, num) => {
return total + num;
}, 0);
console.log(sum); // 15
// Example: Find maximum value
const max = numbers.reduce((maximum, num) => {
return num > maximum ? num : maximum;
}, numbers[0]);
console.log(max); // 5
// Example: Count occurrences
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const count = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
console.log(count); // { apple: 3, banana: 2, orange: 1 }
// Example: Flatten nested arrays
const nested = [[1, 2], [3, 4], [5, 6]];
const flattened = nested.reduce((acc, arr) => {
return acc.concat(arr);
}, []);
console.log(flattened); // [1, 2, 3, 4, 5, 6]
// Example: Group by property
const people = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 25 },
{ name: 'David', age: 30 }
];
const groupedByAge = people.reduce((acc, person) => {
const age = person.age;
if (!acc[age]) {
acc[age] = [];
}
acc[age].push(person.name);
return acc;
}, {});
console.log(groupedByAge);
// { 25: ['Alice', 'Charlie'], 30: ['Bob', 'David'] }
Always provide an initial value to reduce() to avoid unexpected behavior with empty arrays and to make your code more predictable.
π― find() and findIndex() - Locate Elements
find() returns the first element that matches a condition. findIndex() returns its index.
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 }
];
// find() - Returns the first matching element
const user = users.find((user) => user.id === 2);
console.log(user); // { id: 2, name: 'Bob', age: 30 }
const adult = users.find((user) => user.age > 18);
console.log(adult); // { id: 1, name: 'Alice', age: 25 } (first match)
const notFound = users.find((user) => user.age > 40);
console.log(notFound); // undefined
// findIndex() - Returns the index of first matching element
const index = users.findIndex((user) => user.name === 'Charlie');
console.log(index); // 2
const notFoundIndex = users.findIndex((user) => user.age > 40);
console.log(notFoundIndex); // -1
// Practical example: Update specific item
const products = [
{ id: 1, name: 'Laptop', price: 999 },
{ id: 2, name: 'Mouse', price: 29 },
{ id: 3, name: 'Keyboard', price: 79 }
];
const productIndex = products.findIndex((p) => p.id === 2);
if (productIndex !== -1) {
products[productIndex].price = 25; // Update price
}
console.log(products[productIndex]); // { id: 2, name: 'Mouse', price: 25 }
β some() and every() - Test Conditions
some() tests if at least one element passes a condition. every() tests if all elements pass.
const numbers = [1, 2, 3, 4, 5];
// some() - Returns true if ANY element passes the test
const hasEven = numbers.some((num) => num % 2 === 0);
console.log(hasEven); // true (2 and 4 are even)
const hasLarge = numbers.some((num) => num > 10);
console.log(hasLarge); // false
// every() - Returns true if ALL elements pass the test
const allPositive = numbers.every((num) => num > 0);
console.log(allPositive); // true
const allEven = numbers.every((num) => num % 2 === 0);
console.log(allEven); // false (1, 3, 5 are odd)
// Practical example: Form validation
const formFields = [
{ name: 'username', value: 'john_doe', valid: true },
{ name: 'email', value: 'john@example.com', valid: true },
{ name: 'password', value: '123', valid: false }
];
const hasInvalidField = formFields.some((field) => !field.valid);
console.log(hasInvalidField); // true
const allFieldsValid = formFields.every((field) => field.valid);
console.log(allFieldsValid); // false
// Example: Age verification
const people = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 17 }
];
const hasMinor = people.some((person) => person.age < 18);
console.log(hasMinor); // true
const allAdults = people.every((person) => person.age >= 18);
console.log(allAdults); // false
π sort() - Order Elements
sort() sorts the elements of an array in place (mutates the original array).
// Default sort (converts to strings and sorts alphabetically)
const fruits = ['banana', 'apple', 'cherry', 'date'];
fruits.sort();
console.log(fruits); // ['apple', 'banana', 'cherry', 'date']
// WARNING: Default sort on numbers doesn't work as expected!
const numbers = [10, 5, 40, 25, 1000, 1];
numbers.sort();
console.log(numbers); // [1, 10, 1000, 25, 40, 5] (sorted as strings!)
// Correct way to sort numbers: provide compare function
const nums = [10, 5, 40, 25, 1000, 1];
// Ascending order
nums.sort((a, b) => a - b);
console.log(nums); // [1, 5, 10, 25, 40, 1000]
// Descending order
nums.sort((a, b) => b - a);
console.log(nums); // [1000, 40, 25, 10, 5, 1]
// Sort objects by property
const users = [
{ name: 'Charlie', age: 35 },
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 }
];
// Sort by age
users.sort((a, b) => a.age - b.age);
console.log(users);
// [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 35 }
// ]
// Sort by name (alphabetically)
users.sort((a, b) => a.name.localeCompare(b.name));
console.log(users);
// [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 35 }
// ]
// Sort without mutating original (create copy first)
const original = [3, 1, 4, 1, 5, 9];
const sorted = [...original].sort((a, b) => a - b);
console.log(original); // [3, 1, 4, 1, 5, 9] (unchanged)
console.log(sorted); // [1, 1, 3, 4, 5, 9]
sort() modifies the original array! Use the spread operator [...array].sort() if you need to preserve the original.
β©οΈ reverse() - Reverse Order
// reverse() mutates the original array
const numbers = [1, 2, 3, 4, 5];
numbers.reverse();
console.log(numbers); // [5, 4, 3, 2, 1]
const letters = ['a', 'b', 'c', 'd'];
letters.reverse();
console.log(letters); // ['d', 'c', 'b', 'a']
// Reverse without mutating (create copy first)
const original = [1, 2, 3, 4, 5];
const reversed = [...original].reverse();
console.log(original); // [1, 2, 3, 4, 5] (unchanged)
console.log(reversed); // [5, 4, 3, 2, 1]
// Alternative: reverse using other methods
const arr = [1, 2, 3, 4, 5];
const rev = arr.slice().reverse(); // slice() creates copy
console.log(rev); // [5, 4, 3, 2, 1]
π join() - Array to String
// join() converts array to string with separator
const fruits = ['apple', 'banana', 'orange'];
// Default separator is comma
console.log(fruits.join()); // "apple,banana,orange"
// Custom separator
console.log(fruits.join(', ')); // "apple, banana, orange"
console.log(fruits.join(' - ')); // "apple - banana - orange"
console.log(fruits.join('')); // "applebananaorange"
// Practical example: Create sentence
const words = ['JavaScript', 'is', 'awesome'];
const sentence = words.join(' ');
console.log(sentence); // "JavaScript is awesome"
// Practical example: Create CSV
const data = ['John', 'Doe', '30', 'NYC'];
const csv = data.join(',');
console.log(csv); // "John,Doe,30,NYC"
// Split (opposite of join) - String to Array
const text = "hello-world-javascript";
const parts = text.split('-');
console.log(parts); // ['hello', 'world', 'javascript']
const sentence2 = "The quick brown fox";
const words2 = sentence2.split(' ');
console.log(words2); // ['The', 'quick', 'brown', 'fox']
π includes() and indexOf() - Check Existence
const fruits = ['apple', 'banana', 'orange', 'grape'];
// includes() - Returns boolean
console.log(fruits.includes('banana')); // true
console.log(fruits.includes('mango')); // false
// Check from specific index
console.log(fruits.includes('apple', 1)); // false (start from index 1)
// indexOf() - Returns index or -1
console.log(fruits.indexOf('orange')); // 2
console.log(fruits.indexOf('mango')); // -1
// lastIndexOf() - Returns last index
const numbers = [1, 2, 3, 2, 1];
console.log(numbers.indexOf(2)); // 1 (first occurrence)
console.log(numbers.lastIndexOf(2)); // 3 (last occurrence)
// Practical example: Check if item exists before adding
const cart = ['apple', 'banana'];
const newItem = 'orange';
if (!cart.includes(newItem)) {
cart.push(newItem);
}
console.log(cart); // ['apple', 'banana', 'orange']
// Remove item if exists
const items = ['a', 'b', 'c', 'd'];
const toRemove = 'c';
const index = items.indexOf(toRemove);
if (index !== -1) {
items.splice(index, 1);
}
console.log(items); // ['a', 'b', 'd']
βοΈ slice() vs splice() - Extract and Modify
// slice(start, end) - Returns new array, original unchanged
const fruits = ['apple', 'banana', 'orange', 'grape', 'mango'];
const sliced = fruits.slice(1, 4); // From index 1 to 4 (not including 4)
console.log(sliced); // ['banana', 'orange', 'grape']
console.log(fruits); // Original unchanged
// Negative indices (count from end)
const lastTwo = fruits.slice(-2);
console.log(lastTwo); // ['grape', 'mango']
const allButLast = fruits.slice(0, -1);
console.log(allButLast); // ['apple', 'banana', 'orange', 'grape']
// Copy array
const copy = fruits.slice();
console.log(copy); // ['apple', 'banana', 'orange', 'grape', 'mango']
// splice(start, deleteCount, item1, item2, ...) - Modifies original
const fruits = ['apple', 'banana', 'orange', 'grape'];
// Remove elements
const removed = fruits.splice(1, 2); // Remove 2 elements starting at index 1
console.log(removed); // ['banana', 'orange']
console.log(fruits); // ['apple', 'grape'] (original modified)
// Insert elements (deleteCount = 0)
const fruits2 = ['apple', 'grape'];
fruits2.splice(1, 0, 'banana', 'orange'); // Insert at index 1
console.log(fruits2); // ['apple', 'banana', 'orange', 'grape']
// Replace elements
const fruits3 = ['apple', 'banana', 'orange'];
fruits3.splice(1, 1, 'mango', 'kiwi'); // Remove 1, add 2 at index 1
console.log(fruits3); // ['apple', 'mango', 'kiwi', 'orange']
// Remove from specific index to end
const numbers = [1, 2, 3, 4, 5];
numbers.splice(2); // Remove from index 2 to end
console.log(numbers); // [1, 2]
π concat() and flat() - Combine Arrays
// concat() - Merge arrays (returns new array)
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];
const combined = arr1.concat(arr2, arr3);
console.log(combined); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(arr1); // [1, 2, 3] (unchanged)
// Can also add individual elements
const merged = arr1.concat(4, 5, arr2);
console.log(merged); // [1, 2, 3, 4, 5, 4, 5, 6]
// Modern alternative: spread operator
const combined2 = [...arr1, ...arr2, ...arr3];
console.log(combined2); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
// flat() - Flatten nested arrays
const nested = [1, 2, [3, 4], [5, [6, 7]]];
const flattened = nested.flat();
console.log(flattened); // [1, 2, 3, 4, 5, [6, 7]] (1 level deep)
// Specify depth
const deepFlat = nested.flat(2);
console.log(deepFlat); // [1, 2, 3, 4, 5, 6, 7] (2 levels deep)
// Flatten all levels
const fullyFlat = nested.flat(Infinity);
console.log(fullyFlat); // [1, 2, 3, 4, 5, 6, 7]
// flatMap() - map() then flat() in one step
const sentences = ['hello world', 'foo bar'];
const words = sentences.flatMap((sentence) => sentence.split(' '));
console.log(words); // ['hello', 'world', 'foo', 'bar']
βοΈ Chaining Array Methods
Array methods can be chained together to perform complex operations in a readable way.
// Example 1: Filter, map, and sort
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const result = numbers
.filter((num) => num % 2 === 0) // Get even numbers: [2, 4, 6, 8, 10]
.map((num) => num * 2) // Double them: [4, 8, 12, 16, 20]
.sort((a, b) => b - a); // Sort descending: [20, 16, 12, 8, 4]
console.log(result); // [20, 16, 12, 8, 4]
// Example 2: Process user data
const users = [
{ name: 'Alice', age: 25, active: true },
{ name: 'Bob', age: 17, active: false },
{ name: 'Charlie', age: 30, active: true },
{ name: 'David', age: 22, active: true },
{ name: 'Eve', age: 16, active: true }
];
const activeAdultNames = users
.filter((user) => user.active && user.age >= 18) // Active adults only
.map((user) => user.name) // Get names
.sort(); // Sort alphabetically
console.log(activeAdultNames); // ['Alice', 'Charlie', 'David']
// Example 3: Calculate total price with discount
const products = [
{ name: 'Laptop', price: 1000, category: 'electronics' },
{ name: 'Shirt', price: 30, category: 'clothing' },
{ name: 'Phone', price: 800, category: 'electronics' },
{ name: 'Pants', price: 50, category: 'clothing' }
];
const electronicsTotal = products
.filter((p) => p.category === 'electronics')
.map((p) => p.price * 0.9) // 10% discount
.reduce((sum, price) => sum + price, 0);
console.log(electronicsTotal); // 1620
// Example 4: Extract and flatten tags
const posts = [
{ title: 'Post 1', tags: ['javascript', 'web'] },
{ title: 'Post 2', tags: ['react', 'javascript'] },
{ title: 'Post 3', tags: ['css', 'web'] }
];
const uniqueTags = posts
.flatMap((post) => post.tags) // Flatten tags
.filter((tag, index, arr) => arr.indexOf(tag) === index) // Remove duplicates
.sort(); // Sort alphabetically
console.log(uniqueTags); // ['css', 'javascript', 'react', 'web']
- Format each method call on a new line for readability
- Use meaningful variable names for intermediate results if chain gets complex
- Consider performance: chaining creates multiple iterations
- Break complex chains into multiple steps if it improves clarity
β‘ Performance Considerations
// β Bad: Multiple iterations
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const result = numbers
.filter((num) => num % 2 === 0)
.map((num) => num * 2)
.filter((num) => num > 10);
// 3 separate iterations!
// β
Good: Single reduce
const result2 = numbers.reduce((acc, num) => {
if (num % 2 === 0) {
const doubled = num * 2;
if (doubled > 10) {
acc.push(doubled);
}
}
return acc;
}, []);
// 1 iteration only!
console.log(result); // [12, 16, 20]
console.log(result2); // [12, 16, 20]
// When to use chaining vs single loop:
// - Small arrays (< 1000 elements): Use chaining for readability
// - Large arrays or performance-critical: Consider single loop
// - Always measure if performance matters
// Example: Finding and breaking early
const users = [...Array(10000)].map((_, i) => ({ id: i, name: `User${i}` }));
// forEach cannot break early (always iterates all)
// β Bad for large arrays when you just need to find one item
users.forEach((user) => {
if (user.id === 5000) {
// Can't break here!
}
});
// β
Good: Use for...of or find() which can break early
const found = users.find((user) => user.id === 5000);
console.log(found); // Stops at first match
π― Practical Real-World Examples
Example 1: Shopping Cart Calculations
const cartItems = [
{ id: 1, name: 'Laptop', price: 999, quantity: 1, category: 'electronics' },
{ id: 2, name: 'Mouse', price: 29, quantity: 2, category: 'electronics' },
{ id: 3, name: 'Shirt', price: 39, quantity: 3, category: 'clothing' },
{ id: 4, name: 'Keyboard', price: 79, quantity: 1, category: 'electronics' }
];
// Calculate total price
const total = cartItems.reduce((sum, item) => {
return sum + (item.price * item.quantity);
}, 0);
console.log('Total:', total); // 1223
// Calculate total with 10% discount on electronics
const discountedTotal = cartItems.reduce((sum, item) => {
const itemTotal = item.price * item.quantity;
const discount = item.category === 'electronics' ? 0.9 : 1;
return sum + (itemTotal * discount);
}, 0);
console.log('Discounted Total:', discountedTotal.toFixed(2)); // 1113.90
// Get all product names
const productNames = cartItems.map((item) => item.name).join(', ');
console.log('Products:', productNames);
// "Laptop, Mouse, Shirt, Keyboard"
// Count items by category
const itemsByCategory = cartItems.reduce((acc, item) => {
acc[item.category] = (acc[item.category] || 0) + item.quantity;
return acc;
}, {});
console.log(itemsByCategory); // { electronics: 4, clothing: 3 }
Example 2: Data Analysis
const students = [
{ name: 'Alice', scores: [85, 92, 88, 95] },
{ name: 'Bob', scores: [78, 81, 75, 80] },
{ name: 'Charlie', scores: [92, 95, 90, 94] },
{ name: 'David', scores: [88, 85, 87, 86] }
];
// Calculate average score for each student
const averages = students.map((student) => {
const sum = student.scores.reduce((total, score) => total + score, 0);
const average = sum / student.scores.length;
return { name: student.name, average: average };
});
console.log(averages);
// [
// { name: 'Alice', average: 90 },
// { name: 'Bob', average: 78.5 },
// { name: 'Charlie', average: 92.75 },
// { name: 'David', average: 86.5 }
// ]
// Find students with average >= 85
const topStudents = averages
.filter((student) => student.average >= 85)
.map((student) => student.name);
console.log('Top students:', topStudents); // ['Alice', 'Charlie', 'David']
// Calculate class average
const classAverage = students
.flatMap((student) => student.scores)
.reduce((sum, score, _, arr) => sum + score / arr.length, 0);
console.log('Class average:', classAverage.toFixed(2)); // 86.94
Example 3: Text Processing
const text = `
JavaScript is awesome. JavaScript is powerful.
Many developers love JavaScript.
JavaScript JavaScript JavaScript!
`;
// Count word frequency
const wordCount = text
.toLowerCase() // Convert to lowercase
.replace(/[^\w\s]/g, '') // Remove punctuation
.split(/\s+/) // Split by whitespace
.filter((word) => word.length > 0) // Remove empty strings
.reduce((count, word) => {
count[word] = (count[word] || 0) + 1;
return count;
}, {});
console.log(wordCount);
// {
// javascript: 5,
// is: 2,
// awesome: 1,
// powerful: 1,
// many: 1,
// developers: 1,
// love: 1
// }
// Get top 3 most common words
const topWords = Object.entries(wordCount)
.sort((a, b) => b[1] - a[1])
.slice(0, 3)
.map(([word, count]) => ({ word, count }));
console.log('Top 3 words:', topWords);
// [
// { word: 'javascript', count: 5 },
// { word: 'is', count: 2 },
// { word: 'awesome', count: 1 }
// ]
π Quick Reference Table
| Method | Mutates? | Returns | Use Case |
|---|---|---|---|
forEach() |
No | undefined | Execute function for each element |
map() |
No | New array | Transform each element |
filter() |
No | New array | Select elements by condition |
reduce() |
No | Single value | Accumulate to single result |
find() |
No | Element or undefined | Find first matching element |
findIndex() |
No | Index or -1 | Find index of first match |
some() |
No | Boolean | Test if any element matches |
every() |
No | Boolean | Test if all elements match |
sort() |
Yes | Sorted array | Sort elements in place |
reverse() |
Yes | Reversed array | Reverse order in place |
splice() |
Yes | Removed elements | Add/remove elements in place |
slice() |
No | New array | Extract portion of array |
concat() |
No | New array | Merge arrays |
join() |
No | String | Convert array to string |
includes() |
No | Boolean | Check if element exists |
flat() |
No | New array | Flatten nested arrays |
- forEach() iterates but doesn't return anything useful
- map() transforms each element into a new array
- filter() selects elements that match a condition
- reduce() accumulates array into a single value
- find/findIndex() locate specific elements efficiently
- some/every() test conditions across the array
- sort/reverse() modify the original array (mutating)
- Method chaining creates powerful, readable transformations
- Always consider whether a method mutates the original array