[JS] 배열내장함수

Minyoung's Conference·2022년 5월 14일
0

JavaScript

목록 보기
5/28
post-thumbnail

[배열내장함수]

const arr = [1,2,3,4];
for (let i = 0; i < arr.length; i++) {
	console.log(arr[i]);
} 

배열내장함수를 사용하면 위 코드를 한 줄로 줄일 수 있다.

내장함수는 객체의 메서드와 같다.
자바스크립트의 자료형은 모두 객체로 이루어져 있다.

arr.forEach((elm) => console.log(elm));
// 파라미터의 *2값을 출력하고 싶다면? 
arr.forEach((elm) => console.log(elm *2));

forEach() 내장함수는 배열의 모든 요소를 한 번씩 순회할 수 있도록 해주는 메서드이다.
배열 각각의 요소를 forEach() 내부의 콜백함수에 전달된 파라미터를 한 번씩 순회한다. 쉽게 말해 콜백 함수를 한 요소별로 한번 씩 실행한다.

순회하여 값은 2배로 만들 수 있지만 2배한 값을 배열로 만들진 않는다.

const arr = [1,2,3,4];
const newArr = [];

arr.forEach(function (elm) {
	newArr.push(elm *2);
});

console.log(newArr); // [2,4,6,8]

더 짧게 쓴다면, map()을 사용하면 된다.
map()은 내부의 콜백함수에 return을 사용할 수 있다.

const arr = [1,2,3,4];
const newArr = arr.map((elm) => {
	return elm * 2;
})

console.log(newArr); // [2,4,6,8]
0:2
1:4
2:6
3:8

map() 또한 forEach() 처럼 콜백함수를 순회하지만 return이 있어서 각각의 값을 반환한다.
map()은 메모리를 할당하고 리턴 값을 저장, 새로운 array 반환
forEach()는 리턴 값 X, undefined 반환. 현재 array 반환

const arr = [1,2,3,4];
let number = 3;

arr.forEach((elm) => {
	if (elm === numbers) {
    	console.log(true);
    }
})

includes를 사용하면 연산자를 통해 비교하지 않고 메서드를 사용해 바로 true/false를 확인할 수 있다.

console.log(arr.includes(number)); 
// true

includes는 주어진 배열에서 인자가 존재하는지 boolean식으로 확인이 가능하다.

이젠 존재유무에 더해서 몇 번째 인덱스에 존재하는 지 까지 확인하는 메서드가 있는데 이것은 indexOf 이다.

let number = "3";

console.log(arr.indexOf(number));
// -1

결과값이 -1이 나오는 경우는 인자로 존재하지 않는 경우이다.
존재유무를 알 수 있고, 있다면 몇 번째에 위치하는지도 알 수 있게 된다.

하지만, 객체로 이루어진 배열에서는 indexOf, includes와 같은 확인 메서드를 사용하기 힘들 수 있다.

const arr = [
	{color : "red"},
    {color : "black"},
    {color : "blue"},
	{color : "green"}
];

let number = 3;

객체의 순서를 확인하려면 findIndexcallback 함수를 사용하면 된다. callback함수의 결과가 true를 반환하는 로직을 짤 수 있다.

console.log(arr.findIndex((obj) => {
	obj.color === "green" 
}));  

// output : 3 

findIndex도 마찬가지로 요소가 없다면 -1을 반환한다.
일치하는 요소가 2개 이상인 경우, 가장 먼저만난 요소를 반환
배열을 순서대로 순회하기 때문이다.

그렇다면 직접적으로 객체 요소에 접근하고 싶다면 어떻게 해야하는가?

const arr = [
	{color : "red"},
    {color : "black"},
    {color : "blue"},
	{color : "green"}
];

let number = 3;

console.log(
	arr[
    	arr.findIndex((elm) => {
        	return elm.color === "blue";
        })
    ]
);

조금 복잡하다면, 내부의 값을 상수로 변환해주면 된다.

const idx = arr.findIndex((elm) => {
	return elm.color === "blue";
});

console.log(idx); // 2
console.log(arr.[idx]); // {color: 'blue'}

하지만, findIndex도 괜찮지만,
배열의 요소에 직접 접근하는 방법이 있다. find 이다.

find는 인덱스를 가져오는 게 아니라 조건에 부합하는 요소를 그대로 가지고 온다.

const element = arr.find((elm) => {
	return arr.color === "blue";
});

console.log(element); // {color:"blue"}

findIndexfind는 전달하는 콜백함수의 기능은 같다.
(조건을 만족하는 첫 번째 요소를 반환함).

find는 만족하는 요소 자체를 반환
findIndex는 요소의 인덱스를 반환

const arr = [
	{num:1, color : "red"},
    {num:2, color : "black"},
    {num:3, color : "blue"},
	{num:4, color : "green"},
    {num:5, color : "blue"}
];

color가 blue인 것만 필터링 하고 싶다면 어떻게 해야할까?
내장함수 filter를 사용하면 된다.

console.log(arr.filter((elm) => elm.color === "blue"));
// (2) [Object, Object]

조건을 만족하는 요소를 배열로 반환받으려면 filter 를 쓰자.

배열을 원하는 인덱스만큼 자르고 싶다면? slice를 쓰자.

console.log(arr.slice(begin, end)); 

여기서 begin, end에 0,2를 넣어보자

console.log(arr.slice(0, 2)); 
//(2) [Object, Object]

하지만, end부분에 2를 넣으먄 인덱스 1까지 짜른다.
end -1 이라고 생각하면 된다.

slice()는 원본 배열을 변화시키고
filter()map()은 새로운 배열을 반환한다.

이제 잘라봤으니, 다시 붙여보자.
다시 붙이기 위해선, concat()을 쓰면 된다.

const arr1 = [
	{num:1, color : "red"},
    {num:2, color : "black"},
    {num:3, color : "blue"}
];

const arr2 = [
	{num:4, color : "green"},
    {num:5, color : "blue"}
];

console.log(arr1.concat(arr2));

// (5) [Object, Object, Object, Object, Object]

자르는 것과 붙이는 걸 했으니, 이제 정렬을 해보자.

let chars = ["나", "다", "가"];
console.log(chars);
// (3) ['나', '다', '가']

여기서 문자열을 사전식으로 정렬하고 싶다면 sort()를 쓰면된다.

let chars = ["나", "다", "가"];
chars.sort();

console.log(chars);
// (3) ['가', '나', '다']

sort()는 정렬된 배열을 반환하는 게 아니라 원본 배열의 순서를 정렬한다.

이번엔 문자열이 아닌 숫자를 넣어보자.

let numbers = [0,1,3,2,10,30,20];
console.log(numbers);
// (7) [0, 1, 10, 2, 20, 3, 30]

sort()는 숫자가 아닌 문자를 기준으로 정렬한다. (사전순)
그렇기 때문에 sort 메서드에 전달할 비교함수를 만들어 주어야 한다.

const compare = (a,b) => {
	//1. 같다
    //2. 크다
    //3. 작다
    
    if (a > b) {
    	// 크다
        return 1;
    }
    
    if (a < b) {
    	//작다
        return -1;
    
    }
    
    // 같다 
    return 0;
};

numbers.sort(compare); 
console.log(numbers);
// (7) [0, 1, 2, 3, 10, 20, 30]

비교함수를 넣으니 정상적으로 출력되는 것을 알 수 있다.
위의 비교함수를 정확히 이해해보자.

비교함수는 3가지로 비교하고 결과를 내 놓는다.
예를 들어 a = 1, b = 2를 넣는다고 생각해보면,

const compare = (1,2) => {
    if (1 > 2) {
        return 1; // a가  b보다 뒤에 있어야 한다는 뜻, 큰 값이 뒤로 
    }
    if (1 < 2) {
        return -1; // b가 a보다 앞에 있어야 한다는 뜻, 작은 값이 앞으로 가야 한다는 뜻
    
    }
    return 0;
};

음수가 나오면 a가 앞으로, 양수가 나오면 a가 뒤로, 같을 땐 자리를 바꾸지 않는다면 배열의 순서가 오름차순으로 정리가 된다.

만약 내림차순으로 바꾸고 싶다면 비교함수의 return 값
-1 -> 1, 1 -> -1 로 바꾸어 주면 된다.

그래서 이렇게 비교함수를 만들어 sort 메소드에 전달을 한다면,
정수 배열뿐만 아니라, 객체 배열, 배열의 배열, 함수의 배열 또한 원하는대로 정렬할 수 있다.

마지막으로, 모든 문자열들을 합치는 메소드를 알아보자.

const. arr = ["Hi", "bradley", "Good to see you", "again"];

console.log(arr[0], arr[1], arr[2], arr[3]);
// Hi bradley Good to see you again

이 방식은 너무 하드한 방법이다. join()을 쓰자.

const. arr = ["Hi", "bradley", "Good to see you", "again"];

console.log(arr.join());
// Hi,bradley,Good to see you,again

그런데 쉼표로 구분되어 나타난다. 쉼표를 없애려면 공백을 넣어준다.

console.log(arr.join(""));
// Hi bradley Good to see you again

그 말은 즉슨, join안에 들어가는 값은 구분자가 되는 것이다.

console.log(arr.join("-"));
// Hi-bradley-Good to see you-again

원본 배열 데이터 수정 메서드

**shift() : 배열 첫번째 요소 삭제, 결괏값으로 삭제된 원소 반환**
const arr = [1,2];
console.log(arr.shift()); // 1
console.log(arr) // [2] 

**unshift() : 배열 첫 번째 인덱스에 원소 추가, 결괏값으로 배열의 새로운 길이 반환**
const arr = [1,2];
console.log(arr.unshift(-1,0)); // 4
console.log(arr); // [-1, 0, 1, 2]

**push() : 배열 마지막 인덱스에 하나 이상의 원소 추가, 결괏값으로 배열의 새로운 길이 반환**
const arr = [1];
console.log(arr.push(2,3)); // 3
console.log(arr); // [1,2,3]

**pop() : 배열 마지막 인덱스에 해당 원소 삭제, 그 값을 결과값으로 반환**
const arr = [1,2];
console.log(arr.pop()); // 2 
console.log(arr); // [1]

**splice(a,b,c) : 배열 원소 추가, 교체 또는 삭제해 배열 데이터를 변경
								결괏값으로 삭제된 원소 배열 반환 (a:index, b:지울갯수, c:추가요소)**
const arr = [1,2,3];
console.log(arr.splice(1,2, 'a')); // [2,3]
console.log(arr); //[1, a]

arr.**sort(compareFunction) : 정렬 순서를 정의하는 비교 함수를 사용해 정렬.
비교 함수 생략 시, 문자 유니코드 포인트값 따름.** 
const arr = [3,2,4,21,55];
arr.sort();
console.log(arr); // [2, 21, 3, 4, 55]

오름차순 : [1,2,3].sort((a,b) => {a-b}); // [1,2,3]
내림차순 : [1,2,3].sort((a,b) => {b-a}); // [3,2,1]

새로운 배열 생성 메서드

**concat() : 인자로 넘긴 배열 또는 값들을 기존 배열에 합쳐 새로운 배열 생성 반환**
const arr = [1,2,3];
const newArr = arr.concat([4,5]);
console.log(arr); // [1,2,3]
console.log(newArr); // [1,2,3,4,5]

**arr.slice(begin,end) : 배열에서 특정 범위의 원소를 복사해 새로운 배열을 생성 반환.
				(, 얕은 복사를 수행 -> 배열 원소가 객체면 참조 유지)**
const obj = {};
const arr = [1, obj, 3];
const newArr = arr.slice(1,2);
// slice() 메서드는 얕은 복사를 하기 때문에 배열 내에 중첩된 객체의 참조가 유지됨.
console.log(newArr[0] === obj); // true

* 배열 복사 하는 또 다른 방법 -> 전개 연산자 사용 (Spread Operator)
	- slice() 메서드와 마찬가지로 얕은 복사 수행
const arr = [1,2,3];
const newArr = [...arr];
console.log(newArr); // [1,2,3];

**map() : 배열의 모든 원소를 인자로 받은 함수를 실행, 특정한 형식으로 변경, 
				변경한 원소들로 새로운 배열을 생성해 반환**
const arr = [1,2,3];
const newArr = arr.map(x => x+1);
console.log(newArr); // [2,3,4]

**forEach() : 인자로 받은 함수를 배열의 모든 원소를 대상으로 실행, undefined 반환**
const arr = [1,2,3];
const newArr = arr.forEach(x => console.log(x)); // 1, 2, 3
****
**filter() : 인자로 받은 함수의 테스트를 통과하는 원소들로 새로운 배열을 생성해 반환**
const arr = [1,2,3]; 
const newArr = arr.filter(x => x !== 1);
console.log(newArr); // [2,3]
profile
안녕하세요, FE 개발자 김민영입니다.

0개의 댓글