javascript로 코딩테스트를 준비하려는데 Array를 모르면 절대절대 안됩니다.
알고리즘 문제를 풀 때 정말 유용하게 사용되는 배열(Array) 메서드들을 총정리하는 시간을 가져보겠습니다.
배열 메서드를 잘 활용하면 코드를 훨씬 간결하고 효율적으로 작성할 수 있으며, 문제 해결 능력도 크게 향상될 수 있습니다.
배열메서드를 다루면서 가장 중요한 포인트중 하나는 원본배열에 영향을 미치냐 안미치냐입니다.
1. 배열 순회 및 탐색 메서드
배열의 각 요소를 순회하거나 특정 조건을 만족하는 요소를 찾는 메서드들입니다.
1.1 forEach()
- 배열의 각 요소에 대해 주어진 함수를 실행합니다.
- 반환값:
undefined - 주의: 원본 배열을 변경하지는 않지만, 콜백 함수 내에서 원본 배열을 변경하는 작업은 가능합니다.
map,filter와 달리 새로운 배열을 반환하지 않습니다.
const numbers = [1, 2, 3, 4, 5];
let sum = 0;
numbers.forEach(item => {
console.log(item); // 1, 2, 3, 4, 5 순서대로 출력
sum += item;
});
console.log(sum); // 결과: 15
// forEach 자체의 반환값은 undefined 입니다.
const result = numbers.forEach(item => item * 2);
console.log(result); // 결과: undefined
1.2 map()
- 배열의 각 요소에 대해 주어진 함수를 실행하고, 그 결과를 모아 새로운 배열을 반환합니다.
- 원본 배열은 변경되지 않습니다.
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map(item => item * 2);
console.log(doubledNumbers); // 결과: [2, 4, 6, 8, 10]
console.log(numbers); // 결과: [1, 2, 3, 4, 5] (원본 배열은 그대로)
1.3 filter()
- 배열의 각 요소에 대해 주어진 함수의 조건을 만족하는(true를 반환하는) 요소들만 모아 새로운 배열을 반환합니다.
- 원본 배열은 변경되지 않습니다.
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(item => item % 2 === 0);
console.log(evenNumbers); // 결과: [2, 4]
console.log(numbers); // 결과: [1, 2, 3, 4, 5] (원본 배열은 그대로)
1.4 reduce()
- 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하여 하나의 결과값을 반환합니다. (누산기)
accumulator: 누적값,currentValue: 현재 요소,currentIndex(옵션): 현재 인덱스,array(옵션): 원본 배열initialValue(옵션): 초기 누적값
const numbers = [1, 2, 3, 4, 5];
// 합계 구하기
const sum = numbers.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
}, 0); // 초기값 0
console.log(sum); // 결과: 15
// 최대값 구하기
const max = numbers.reduce((acc, cur) => (cur > acc ? cur : acc), numbers[0]);
console.log(max); // 결과: 5
1.5 reduceRight()
reduce()와 동일한 기능을 하지만, 배열의 오른쪽부터 왼쪽으로 함수를 실행합니다.
const strings = ['world', ' ', 'hello'];
const combinedString = strings.reduceRight((acc, cur) => acc + cur);
console.log(combinedString); // 결과: "hello world"
1.6 find()
- 배열에서 주어진 판별 함수를 만족하는 첫 번째 요소의 값을 반환합니다. 만족하는 요소가 없으면
undefined를 반환합니다.
const numbers = [1, 3, 5, 4, 7];
const firstEven = numbers.find(item => item % 2 === 0);
console.log(firstEven); // 결과: 4
const notFound = numbers.find(item => item > 10);
console.log(notFound); // 결과: undefined
1.7 findIndex()
- 배열에서 주어진 판별 함수를 만족하는 첫 번째 요소의 인덱스를 반환합니다. 만족하는 요소가 없으면
-1을 반환합니다.
const numbers = [1, 3, 5, 4, 7];
const firstEvenIndex = numbers.findIndex(item => item % 2 === 0);
console.log(firstEvenIndex); // 결과: 3
const notFoundIndex = numbers.findIndex(item => item > 10);
console.log(notFoundIndex); // 결과: -1
1.8 some()
- 배열의 요소 중 하나라도 주어진 판별 함수를 만족하면
true를 반환하고, 그렇지 않으면false를 반환합니다.
const numbers = [1, 3, 5, 4, 7];
const hasEvenNumber = numbers.some(item => item % 2 === 0);
console.log(hasEvenNumber); // 결과: true
const hasNumberGreaterThan10 = numbers.some(item => item > 10);
console.log(hasNumberGreaterThan10); // 결과: false
1.9 every()
- 배열의 모든 요소가 주어진 판별 함수를 만족하면
true를 반환하고, 그렇지 않으면false를 반환합니다.
const numbers = [2, 4, 6, 8];
const allEven = numbers.every(item => item % 2 === 0);
console.log(allEven); // 결과: true
const numbers2 = [2, 4, 7, 8];
const allEven2 = numbers2.every(item => item % 2 === 0);
console.log(allEven2); // 결과: false
1.10 includes()
- 배열이 특정 요소를 포함하고 있는지 판별하여
true또는false를 반환합니다. fromIndex(옵션): 검색을 시작할 인덱스
const fruits = ['apple', 'banana', 'mango'];
console.log(fruits.includes('banana')); // 결과: true
console.log(fruits.includes('grape')); // 결과: false
console.log(fruits.includes('apple', 1)); // 결과: false (인덱스 1부터 검색)
1.11 indexOf()
- 배열에서 지정된 요소를 찾을 수 있는 첫 번째 인덱스를 반환합니다. 요소가 없으면
-1을 반환합니다. fromIndex(옵션): 검색을 시작할 인덱스
const fruits = ['apple', 'banana', 'mango', 'banana'];
console.log(fruits.indexOf('banana')); // 결과: 1
console.log(fruits.indexOf('grape')); // 결과: -1
console.log(fruits.indexOf('banana', 2)); // 결과: 3 (인덱스 2부터 검색)
1.12 lastIndexOf()
- 배열에서 지정된 요소를 찾을 수 있는 마지막 인덱스를 반환합니다. 요소가 없으면
-1을 반환합니다. fromIndex(옵션): 검색을 시작할 인덱스 (역방향으로 검색)
const fruits = ['apple', 'banana', 'mango', 'banana'];
console.log(fruits.lastIndexOf('banana')); // 결과: 3
console.log(fruits.lastIndexOf('grape')); // 결과: -1
console.log(fruits.lastIndexOf('banana', 2)); // 결과: 1 (인덱스 2부터 역방향 검색)
2. 배열 수정 메서드 (원본 배열 변경)
다음 메서드들은 원본 배열 자체를 변경합니다. 그러므로 사용 시 주의가 필요합니다.
2.1 push()
- 배열의 끝에 하나 이상의 요소를 추가하고, 배열의 새로운 길이를 반환합니다.
const numbers = [1, 2, 3];
const newLength = numbers.push(4, 5);
console.log(newLength); // 결과: 5
console.log(numbers); // 결과: [1, 2, 3, 4, 5] (원본 배열 변경)
2.2 pop()
- 배열의 마지막 요소를 제거하고, 그 제거된 요소를 반환합니다. 배열이 비어있으면
undefined를 반환합니다.
const numbers = [1, 2, 3, 4, 5];
const lastElement = numbers.pop();
console.log(lastElement); // 결과: 5
console.log(numbers); // 결과: [1, 2, 3, 4] (원본 배열 변경)
2.3 shift()
- 배열의 첫 번째 요소를 제거하고, 그 제거된 요소를 반환합니다. 배열이 비어있으면
undefined를 반환합니다.
const numbers = [1, 2, 3, 4, 5];
const firstElement = numbers.shift();
console.log(firstElement); // 결과: 1
console.log(numbers); // 결과: [2, 3, 4, 5] (원본 배열 변경)
2.4 unshift()
- 배열의 앞에 하나 이상의 요소를 추가하고, 배열의 새로운 길이를 반환합니다.
const numbers = [3, 4, 5];
const newLength = numbers.unshift(1, 2);
console.log(newLength); // 결과: 5
console.log(numbers); // 결과: [1, 2, 3, 4, 5] (원본 배열 변경)
2.5 splice()
- 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가하여 배열의 내용을 변경합니다.
start: 변경을 시작할 인덱스deleteCount(옵션): 제거할 요소의 수item1, item2, ...(옵션): 배열에 추가할 요소- 반환값: 제거된 요소들의 배열
const months = ['Jan', 'March', 'April', 'June'];
// 요소 삽입 (인덱스 1에 'Feb' 삽입)
let removed = months.splice(1, 0, 'Feb');
console.log(months); // 결과: ['Jan', 'Feb', 'March', 'April', 'June']
console.log(removed); // 결과: [] (제거된 요소 없음)
// 요소 교체 (인덱스 4의 'June'을 'May'로 교체)
removed = months.splice(4, 1, 'May');
console.log(months); // 결과: ['Jan', 'Feb', 'March', 'April', 'May']
console.log(removed); // 결과: ['June'] (제거된 요소)
// 요소 제거 (인덱스 1부터 2개 요소 제거)
removed = months.splice(1, 2);
console.log(months); // 결과: ['Jan', 'April', 'May']
console.log(removed); // 결과: ['Feb', 'March'] (제거된 요소)
2.6 sort()
- 배열의 요소를 정렬합니다. 기본 정렬 순서는 문자열 유니코드 코드 포인트를 따릅니다.
- 주의: 숫자 정렬 시에는 비교 함수를 제공해야 합니다.
- 반환값: 정렬된 배열 (원본 배열 자체가 변경됨)
const fruits = ['banana', 'apple', 'mango'];
fruits.sort();
console.log(fruits); // 결과: ['apple', 'banana', 'mango'] (문자열 정렬)
const numbers = [10, 5, 100, 1];
// 기본 정렬 (문자열 기준으로 정렬되어 의도와 다를 수 있음)
// numbers.sort();
// console.log(numbers); // 결과: [1, 10, 100, 5]
// 숫자 오름차순 정렬
numbers.sort((a, b) => a - b);
console.log(numbers); // 결과: [1, 5, 10, 100]
// 숫자 내림차순 정렬
numbers.sort((a, b) => b - a);
console.log(numbers); // 결과: [100, 10, 5, 1]
2.7 reverse()
- 배열의 요소 순서를 반대로 뒤집습니다.
- 반환값: 순서가 뒤집힌 배열 (원본 배열 자체가 변경됨)
const numbers = [1, 2, 3, 4, 5];
numbers.reverse();
console.log(numbers); // 결과: [5, 4, 3, 2, 1] (원본 배열 변경)
2.8 fill()
- 배열의 시작 인덱스부터 끝 인덱스 이전까지의 모든 요소를 정적인 값으로 채웁니다.
value: 채울 값start(옵션): 시작 인덱스 (기본값 0)end(옵션): 끝 인덱스 (기본값array.length)- 반환값: 변경된 배열 (원본 배열 자체가 변경됨)
const numbers = [1, 2, 3, 4, 5];
// 모든 요소를 0으로 채우기
numbers.fill(0);
console.log(numbers); // 결과: [0, 0, 0, 0, 0]
const numbers2 = [1, 2, 3, 4, 5];
// 인덱스 2부터 4 이전까지 9로 채우기
numbers2.fill(9, 2, 4);
console.log(numbers2); // 결과: [1, 2, 9, 9, 5]
2.9 copyWithin()
- 배열의 일부를 복사하여 동일한 배열의 다른 위치에 덮어쓰고, 길이를 수정하지 않고 반환합니다.
target: 복사한 시퀀스를 붙여넣을 인덱스start(옵션): 복사를 시작할 인덱스 (기본값 0)end(옵션): 복사를 끝낼 인덱스 (기본값array.length)- 반환값: 변경된 배열 (원본 배열 자체가 변경됨)
const array = ['a', 'b', 'c', 'd', 'e'];
// 인덱스 0부터 2개 요소('a', 'b')를 복사해서 인덱스 3 위치부터 붙여넣기
array.copyWithin(3, 0, 2);
console.log(array); // 결과: ['a', 'b', 'c', 'a', 'b']
const array2 = [1, 2, 3, 4, 5];
// 인덱스 0부터 끝까지 복사해서 인덱스 2 위치부터 붙여넣기 (기본값 사용)
array2.copyWithin(2);
console.log(array2); // 결과: [1, 2, 1, 2, 3]
3. 배열 변환 및 생성 메서드 (주로 새로운 배열 반환)
3.1 slice()
- 배열의
begin인덱스부터end인덱스 이전까지에 대한 얕은 복사본을 새로운 배열 객체로 반환합니다. - 원본 배열은 변경되지 않습니다.
begin(옵션): 추출 시작 인덱스 (음수면 끝에서부터의 길이)end(옵션): 추출 종료 인덱스 (해당 인덱스 직전까지 추출, 음수면 끝에서부터의 길이)
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2)); // 결과: ['camel', 'duck', 'elephant']
console.log(animals.slice(2, 4)); // 결과: ['camel', 'duck']
console.log(animals.slice(1, -1)); // 결과: ['bison', 'camel', 'duck']
console.log(animals.slice(-2)); // 결과: ['duck', 'elephant']
console.log(animals.slice()); // 결과: ['ant', 'bison', 'camel', 'duck', 'elephant'] (배열 전체 얕은 복사)
console.log(animals); // 결과: ['ant', 'bison', 'camel', 'duck', 'elephant'] (원본 배열 그대로)
3.2 concat()
- 인자로 주어진 배열이나 값들을 기존 배열에 합쳐 새로운 배열을 반환합니다.
- 원본 배열은 변경되지 않습니다.
const arr1 = ['a', 'b', 'c'];
const arr2 = ['d', 'e', 'f'];
const arr3 = arr1.concat(arr2, 'g');
console.log(arr3); // 결과: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
console.log(arr1); // 결과: ['a', 'b', 'c'] (원본 배열 그대로)
console.log(arr2); // 결과: ['d', 'e', 'f'] (원본 배열 그대로)
3.3 join()
- 배열의 모든 요소를 연결하여 하나의 문자열로 만듭니다.
separator(옵션): 각 요소를 구분할 문자열 (기본값은 쉼표,)
const elements = ['Fire', 'Air', 'Water'];
console.log(elements.join()); // 결과: "Fire,Air,Water"
console.log(elements.join('')); // 결과: "FireAirWater"
console.log(elements.join('-')); // 결과: "Fire-Air-Water"
console.log(elements.join(' ')); // 결과: "Fire Air Water"
3.4 flat()
- 모든 하위 배열 요소를 지정한 깊이까지 재귀적으로 이어붙인 새로운 배열을 생성합니다.
depth(옵션): 중첩 배열 구조를 평탄화할 깊이 (기본값 1)
const arr1 = [1, 2, [3, 4]];
console.log(arr1.flat()); // 결과: [1, 2, 3, 4] (depth 1)
const arr2 = [1, 2, [3, 4, [5, 6]]];
console.log(arr2.flat()); // 결과: [1, 2, 3, 4, [5, 6]] (depth 1)
console.log(arr2.flat(2)); // 결과: [1, 2, 3, 4, 5, 6] (depth 2)
const arr3 = [1, 2, [3, 4, [5, 6, [7, 8]]]];
console.log(arr3.flat(Infinity)); // 결과: [1, 2, 3, 4, 5, 6, 7, 8] (모든 깊이 평탄화)
3.5 flatMap()
- 먼저 배열의 각 요소에 대해 매핑 함수를 실행한 다음, 결과를 새로운 배열로 평탄화합니다. (
map()+flat(1)과 동일)
const arr = [1, 2, 3, 4];
// 각 숫자를 자신과 자신의 제곱으로 매핑 후 평탄화
const result = arr.flatMap(x => [x, x * 2]);
console.log(result); // 결과: [1, 2, 2, 4, 3, 6, 4, 8]
// map과 flat을 사용한 동일한 결과
const resultMap = arr.map(x => [x, x * 2]); // [[1, 2], [2, 4], [3, 6], [4, 8]]
const resultFlat = resultMap.flat(); // [1, 2, 2, 4, 3, 6, 4, 8]
console.log(resultFlat); // 결과: [1, 2, 2, 4, 3, 6, 4, 8]
4. 배열 유틸리티 메서드
4.1 Array.isArray()
- 인자가 배열인지 아닌지 판별합니다. (Array 프로토타입 메서드가 아닌 Array의 정적 메서드)
console.log(Array.isArray([1, 2, 3])); // 결과: true
console.log(Array.isArray({foo: 123})); // 결과: false
console.log(Array.isArray('hello')); // 결과: false
console.log(Array.isArray(undefined)); // 결과: false
4.2 Array.from()
- 유사 배열 객체(array-like object)나 반복 가능한 객체(iterable object)를 얕게 복사하여 새로운 Array 객체를 만듭니다.
(Array 프로토타입 메서드가 아닌 Array의 정적 메서드) - 매핑 함수를 인자로 받을 수 있습니다.
// 문자열로부터 배열 생성
const str = 'hello';
const arr1 = Array.from(str);
console.log(arr1); // 결과: ['h', 'e', 'l', 'l', 'o']
// Set 객체로부터 배열 생성
const set = new Set(['a', 'b', 'c']);
const arr2 = Array.from(set);
console.log(arr2); // 결과: ['a', 'b', 'c']
// 매핑 함수 사용
const numbers = [1, 2, 3];
const arr3 = Array.from(numbers, x => x * x);
console.log(arr3); // 결과: [1, 4, 9]
// 유사 배열 객체 (arguments)
function createArray() {
return Array.from(arguments);
}
const arr4 = createArray(10, 20, 30);
console.log(arr4); // 결과: [10, 20, 30]
5. (번외) 배열 복사: Spread Syntax (...)
- ES6 문법인 전개 구문(...)을 사용하여 배열을 얕게 복사할 수 있습니다.
slice()와 유사하게 사용됩니다.
const original = [1, 2, 3];
const copy = [...original];
copy.push(4);
console.log(original); // 결과: [1, 2, 3] (원본은 변경되지 않음)
console.log(copy); // 결과: [1, 2, 3, 4]
지금까지 알고리즘 문제 풀이에 자주 사용되는 JavaScript 배열 메서드들을 살펴보았습니다.
각 메서드의 특징과 반환값을 정확히 이해하고 상황에 맞게 활용하는 것이 중요합니다.
- 원본 배열 변경 여부:
push,pop,shift,unshift,splice,sort,reverse,fill,copyWithin등은 원본 배열을 직접 수정하므로 주의해야 합니다. - 새로운 배열 반환:
map,filter,slice,concat,flat,flatMap등은 새로운 배열을 반환하므로 함수형 프로그래밍 스타일에 유용합니다.
추가로 배열에서 재미난 문제가 하나있습니다
// 배열은 요소를 동적으로 추가할수있습니다. 이때 length의 프로퍼티 값은 자동으로 갱신되는데요.
const arr = [0];
arr[1] = 1;
console.log(arr) // [0,1]
consoel.log(arr.length) // 2
//여기까지는 뭐 이해가됩니다 근데 갑자기
arr[100] = 100;
// 이걸해버린다면 어떻게될까요?
console.log(arr) // [0,1,empty*98,100]
consoel.log(arr.length) // 101
//이렇게 희소배열이 됩니다!
이건 그냥 배열 공부하다가 생각해보지않았어서 몰랐던 내용이였어요.
이렇게 배열의 요소가 연속적으로 위치하지않고 일부가 비어있는 배열을 희소배열이라고해요 !
배열에 대해서 알아보는 포스팅도 올려보겠습니다.
'JavaScript' 카테고리의 다른 글
| 🛡️ 자바스크립트 Proxy: 내 객체를 위한 똑똑한 문지기 (4) | 2025.04.16 |
|---|---|
| 🔒 Object.freeze()로 안전하게 상태를 보호하는 법 — 불변성(immutability)의 모든 것 (3) | 2025.04.15 |
