javascript의 배열에 대해 정리해 보자
배열은 무엇인가? 한 마디로 순서가 있는 값이다.
let arr = [ 1, 2, 3, 4, 5];
대괄호(square bracket)를 이용해 element들을 그 안에 넣고, comma로 각 element를 구분한다.
배열에는 원본이 수정되는 메소드가 있고, 원본이 수정되지 않는 메소드가 있다.
-
기존의 배열을 수정하는 메소드: push, pop, shift, unshift
-
기존의 배열을 수정하지 않는(원본유지) 메소드: slice, split, join, concat
배열의 길이를 알기 위해서는 length를 사용하면 된다.
let arr = [ 1, 2, 3, 4, 5];
arr.length; //5
push, pop, shift, unshift:
- push는 맨 마지막에 element를 추가, pop()는 맨 마지막 element를 제거한다.
- unshift는 맨 처음에 element를 추가, shift는 맨 처음에 element를 제거한다.
push() : 배열의 element를 맨 마지막 index에 추가한다.
let arr = [ 1, 2, 3, 4, 5];
arr.push(100);
arr; // [1,2,3,4,5,100]
함수와 객체, 배열을 typeof를 해 보면 전부 Object로 나온다. 주어진 것이 배열인지 알기 위해서는 Array.isArray를 사용하면 된다.
typeof 111; //"number"
typeof 'hello'; //"string"
typeof true; //"boolean"
//null, 객체, 배열의 type은 전부 object이다.
typeof null; //"object"
typeof []; //"object"
typeof {}; //"object"
typeof function(){} //"function"
typeof undefined; //"undefined"
오늘 코플릿 문제를 풀면서 가장 힘들었던 부분이 join과 concat, split부분이었다. 그 부분을 중점적으로 정리해본다.
join() : 배열의 모든 요소를 연결해 하나의 문자열을 만든다. 구분자 separator는 생략가능하고 기본 구분자는 콤마(',')
arr.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"
////////////////////////
let arr = [1,2,3,4];
arr.join(); // "1,2,3,4" 배열을 문자열로 전환시킨 후 기본구문자 ','로 연결한 문자열을 반환한다
arr.join(''); // "1234" 문자열로 전환시킨후 빈문자열로 연결한 문자열을 반환한다.
arr.join(':'); // "1:2:3:4" 문자열로 전환시킨후 ':'로 연결한 문자열을 반환한다
arr.join('-'); // "1-2-3-4" 문자열로 전환시킨후 '-'로 연결한 문자열을 반환한다.
기본구분자가 ','이기 때문에 join()에 ( )안에 separator가 없어도 ','로 조인된다.
다음의 문제를 생각해 보자.
let arr = [0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8];
arr를 다음과 같은 문자열로 반환하려면 어떻게 해야 할까? join를 사용해서 생각해 보자
'(010)1234-5678'
풀이
1. [0,1,0 ...] 을 (010)으로 전환해야 한다.
1-1. slice를 사용해서 arr에서 [0,1,0]을 잘라낸다.
arr.slice(0,3);
1-2. 배열을 문자열로 전환한 후 빈문자열로 연결한 문자열을 반환해야 한다.
0,1,0을 010으로 전환하려면 join('')을 사용하면 된다. 원래 조인의 parameter로 separator가 들어가야 하는데 생략한 경우, 기본 구분자(separator)는 ','이다. 그런데 join('')을 하게 되면 그 콤마(',')가 사라지고 010과 같이 연결된 문자열로 결합하게 된다.
arr.slice(0,3).join('');
1-3. template literal를 사용해서 '(010)'의 형태로 전환한다.
let first = `(${arr.slice(0,3).join('')})`;
2. [0,1,0,1,2,3,4,5,6,7,8]를 1234-5678로 전환해야 한다.
2-1. arr.slice와 join을 통해 [1,2,3,4]을 1234로 만든다.
let body = arr.slice(3,7);
let tali = arr.slice(7);
2-2. first, body와 tail를 template literal로 연결한다.
return `${first}${body}-${tail}`;
concat: 인수로 전달된 값을 원본 배열의 마지막에 추가한 새로운 배열을 반환한다. 배열인 경우 배열을 해체하고 새로운 배열의 element를 추가한다. 원본은 변경되지 않는다.
let arr1 = [1,2];
let arr2 = [3,4];
[1,2,3,4]로 만들려면 어떻게 해야 할까?
arr1.concat(arr2); // [1,2,3,4]
//만약 arr1에 3을 추가하고 싶으면 concat를 사용해서 어떻게 해야할까?
arr1.concat(3); // [1,2,3]
//arr1 원본 배열은 변경되지 않는다.
arr1; // [1,2]
let hege = ["Cecilie", "Lone"];
let stale = ["Emil", "Tobias", "Linus"];
let children = hege.concat(stale);
console.log(children); //["Cecilie", "Lone", "Emil", "Tobias", "Linus"]
concat메소드 대신 push나 unshift 메소드를 사용할 수 있다. 다음과 같은 차이가 있다.
- push나 unshift는 원본 배열을 변경하지만 concat는 원본 배열을 변경하지 않고 새로운 배열을 반환한다
- 인수로 전달받은 값이 배열인 경우, push나 unshift는 배열을 그대로 원본 배열의 마지막/첫번째 요소에 추가하지만, concat는 인수로 전달받은 배열을 해체하고 새로운 배열의 마지막 요소에 추가한다.
//push, unshift는 인수로 전달받은 배열을 그대로 원본 배열의 element로 추가한다.
let arr = [3,4];
arr.unshift([1,2]);
arr.push([5,6]);
arr; //[[1,2],3,4,[5,6]]
//concat메소드는 인수로 전달받은 배열을 해체하고 새로운 배열의 element로 추가한다
let result = [1,2].concat([3,4]);
result = result.concat([5,6]);
result; // [1,2,3,4,5,6]
ES6에서 concat대신 spread syntax 문법으로 대체할 수 있다.
let result = [1,2].concat([3,4]);
result; // [1,2,3,4]
//concat메소드는 spread 문법으로 대체할 수 있다.
result = [ ...[1,2], ...[3,4]];
result; // [1,2,3,4]
slice(start, end) : 인수로 전달된 범위의 요소를 복사하여 배열로 반환한다. 원본 배열은 변경되지 않는다.
let arr = [1,2,3,4,5];
//start는 포함하고 end는 포함하지 않고 이전까지 복사하여 반환한다.
arr.slice(0,2); // [1,2]
//end가 없으면 arr[1]이후 모든 요소를 복사하여 반환한다.
arr.slice(1); // [2,3,4,5]
//start에 음수가 들어올 수 있다. 숫자만큼 배열의 마지막 element를 반환한다.
arr.slice(-1); // [5]
arr.slice(-2); // [4,5]
slice메서드의 인수를 생략하면 원본 배열의 복사본을 생성하여 반환한다.
let arr = [1,2,3];
let result = arr.slice();
console.log(result); // [1,2,3]
//이때 생성된 복사본은 얕은 복사(shallow copy)
문제: 함수 addToBackOfNew를 생각해 보자. 이 함수는 [1,2]와 같은 array에 추가할 element 3를 배열 맨 뒤에 새로운 배열을 담는 것이다. (단, 입력받은 배열은 변경되지 않아야 합니다)
let arr = [1,2];
let output = addToBackOfNew(arr, 3); 일때
[1,2,3] 이렇게 새로운 배열을 리턴하려면 어떻게 해야 할까?
function addToBackOfNew(arr, element) {
//to-do
}
풀이
맨 뒤에 새로운 element를 추가하려면 push를 사용하면 된다.
function addToBackOfNew(arr, element) {
return arr.push(element);
}
arr; // [1,2,3] 이 된다. 그런데 이렇게 하면 안된다.
문제의 조건 중에 원본이 수정되지 않아야 한다고 하는데 원본은 [1,2]인데 새로운 배열은 arr이 [1,2,3]으로 변경되었다.
그렇다면 어떻게 하면 원본을 변경하지 않고 element를 배열의 맨 뒤에 추가할 수 있을까?
여기에서 활용할 수 있는 것이 바로 arr.slice() 이다. arr.slice()는 얕은 복사(shallow copy)가 된다.
arr.slice()를 활용하여 수정해 보면 다음과 같다.
function addToBackOfNew(arr, element) {
//새로운 배열을 담을 변수에 arr.slice()를 할당한다.
let newArr = arr.slice(); // arr.slice()는 arr안의 모든 element를 복사한다.
return newArr.push(element);
}
댓글