javascript array

박종대·2022년 2월 5일
0

Javascript / Typescript

목록 보기
2/4

원소를 추가하고 제거하고 싶어요

push : 맨 끝에 추가
pop : 맨 끝 제거
unshift : 맨 앞 추가
shift : 맨 앞 제거

push와 pop은 자바의 스택 자료구조에서 보던 메서드입니다. 스택은 후입선출이죠? 맨 끝에 삽입하고 맨 끝을 제거합니다.

자바스크립트의 배열은 스택과 큐로써 동시에 이용할 수 있다는 특징을 알 수 있네요
shift와 unshift는 각각 맨 앞을 제거하고 추가할 수 있습니다.

특정 위치의 원소를 지우고 싶어요

splice(index [, deleteCount, eles~~])

index는 지우고 싶은 원소의 위치입니다. deleteCount는 그로부터 몇 개를 지울지를 나타내고 eles들은 그 후에 추가할 원소들을 나타냅니다.
가만 보니 splice는 정말 유용할 것 같습니다. 원하는 위치의 원소를 지울수 있는데 몇 개를 지울지 설정 가능하고 거기에 어떤 원소로 대체로 추가할지 까지 설정 가능하다? 만능 메서드인 것 같습니다.

delete arr[index] 는?

delete는 해당 index의 값을 지워 undefined로 만들 뿐 splice 처럼 완전 삭제가 되지 않습니다!

배열의 특정 범위만 복사해오고 싶어요

slice(start, end)

start 인덱스부터 end 인덱스 바로 직전까지 범위를 복사한 '새로운' 배열을 리턴합니다.

범위가 인자로 주어질 때 end 인덱스는 항상 미포함하는데 이는 거의 모든 프로그래밍 언어에서 그런 것 같습니다.

새로운 배열을 리턴한다고 했습니다. 앞의 splice와 비교해보면 arr.splice를 호출하여 특정 작업을 하면 arr 본체가 바뀌어 버립니다. 하지만 slice는 복사본을 만들뿐 arr 본체에 영향이 가지 않습니다.
그럼 slice에 아무런 인자를 주지 않고 혹은 0과 arr.length 인자를 주고 호출한다면 arr 배열의 복사본을 만들 수 있겠습니다!

let arrCopy = arr.slice(); // arr의 복사본 생성

배열을 합치고 싶어요

concat(arr1, arr2, 3, 4)

인자를 모두 원소로 가지는 새로운 배열을 하나 생성합니다!

배열을 순회하고 싶어요

첫번째로 떠올릴 수 있는 것이 반복문입니다!

for(let i = 0; i < arr.length; i++)
for(let element of arr)
for(let index in arr)

  • for ~ in은 객체의 프로퍼티를 순회하는 것으로도 사용

다음은 forEach 메서드가 있습니다.

arr.forEach( (item, index, array) => {} )

요소를 순회하면서 콜백함수의 로직을 수행합니다.

배열의 특정 원소가 어디 있는지 알고 싶어요

arr.indexOf(item, fromIndex)
arr.lastIndexOf(item, fromIndex)
arr.includes(item, from)

indexOf는 fromIndex부터 시작해서 item 요소를 찾아 냅니다. 찾아지면 해당 요소의 '인덱스'를 반환하고 없으면 -1을 리턴합니다.
lastIndexOf는 indexOf와 동일하지만 끝에서부터 찾아 나간다는 점이 다릅니다.
includes는 해당 요소를 발견하면 true를 리턴합니다.

참고로 indexOf 계열은 === 비교로 원소를 찾아내기 때문에
다음과 같은 코드는 원하는 대로 동작하지 않습니다.

const arr = [NaN];
alert( arr.indexOf(NaN)); // -1 리턴, ===은 NaN을 구별 못함

하지만 includes는 정상적으로 동작합니다. 그래서 있는지 없는지 유무만 따지고 싶을때는 includes를 사용합시다!

추가적으로 배열의 원소가 전부 객체라면 어떻게 찾아낼 수 있을까요? 분명 indexOf 계열은 === 으로 비교하기 때문에 객체로 이루어진 배열에서는 정상적으로 동작하지 않을 것입니다. 해결은 다음과 같습니다.

find( (item, index, array) => {} )

find의 인자로 주어진 콜백함수에서 true가 리턴되면 반복을 멈추고 해당 요소를 반환합니다. 해당되는 요소가 없다면 undefined를 반환합니다. 콜백 함수에 해당 객체를 찾는 로직을 구현하면 되겠죠?

findIndex( (item, index, array) => {} )

find와 동일하지만 리턴하는 것이 index입니다! (없으면 -1)

배열의 특정 원소를 찾고 싶긴 한데 여러개가 있어요

let results = arr.filter( (item, index, array) => {} )

조건을 충족하는 요소를 모두 찾아서 반환합니다.

map

배열 요소 전체를 대상으로 함수를 호출하고, 함수 호출 결과를 배열로 반환 해줍니다.

let lengths = ["aaa", "bbbbbb", "cccccccc"].map( (item) => item.length);

lengths에는 원소들의 길이 3, 6, 8을 원소로 가지는 배열이 대입 됩니다.
배열을 순회하면서 배열 원소 각각에 특정 작업을 하여 새로운 원소를 뽑아내서 새로운 배열을 리턴하는 중요한 메서드입니다.

reduce

arr.reduce( (accumulator, item, index, array) => {} )
배열을 기반으로 값 하나를 도출할 때 사용된다고 합니다. 사용법이 조금 복잡하니까 예시로 살펴봐야겠습니다!

let arr = [3, 4, 1, 7, 8];
let result = arr.reduce( (sum, current) => sum + current, 0 ); // 23

accumulator가 sum이고 item이 current가 되겠습니다. accumulator는 이전 함수 호출의 결과입니다. 그럼 맨 처음의 결과는 어떻게 알까요? 두 번째 인자로 주어진 0이 초기값을 나타냅니다. 초기값은 옵션이라고 하는데 초기값이 없으면요? 배열의 첫 번째 요소를 초깃값으로 사용하고 두 번째 요소부터 함수를 호출합니다. (하지만 초깃값은 명시하는 것을 권장한다고 합니다.)

그렇다면 위 코드는 sum에 계속해서 sum + current가 쌓이게 되고 결국 최종 sum이 result가 되어 모든 원소의 합이 result에 대입 됩니다.

사실 reduce의 특성을 보시면 아시겠지만 뭔가 누적된다는 느낌입니다. 그래서 덧셈을 예시로 많이 드는데 이전에 계산 혹은 처리된 결과를 다음 반복 때도 이용한다는 개념을 가지고 있다면 다른 부분에서도 충분히 사용될 수 있을 것입니다.
추가적으로 reduceRight는 배열의 마지막부터 순회한다는 차이점이 있네요.

배열인지 아닌지 알고 싶어요

Array.isArray(알아보고 싶은 변수);

배열 원소를 역순으로 만들고 싶어요

arr.reverse();

split, join

split(delimiter)

delimiter 기준으로 문자열을 분리하여 배열을 리턴해줍니다.

join(delimiter)

배열 요소 모두 사이에 delimiter를 붙여서 하나의 문자열로 합쳐줍니다.

split의 delimiter를 '' 으로 주면 문자열을 한 음절 단위로 분리할 수 있겠습니다.
join 역시 delimiter를 '' 으로 준다면 그냥 배열의 원소를 하나의 문자열로 합칠 수 있겠습니다!

정렬하고 싶어요

arr.sort();

해당 메서드를 호출하면 arr 배열 내부를 오름차순으로 정렬해줍니다. 하지만 배열의 요소가 number 더라도 문자형으로 변환된 이후에 재정렬되기 때문에 원하는 결과를 얻지 못할 수도 있습니다. 또한 배열의 요소가 객체라면 객체를 비교하는 기준은 없기 때문에 원하는 결과를 얻을 수 없습니다.

그렇다면 비교의 기준을 직접 생성해줘야 하겠습니다. 자바에서 Comparator 클래스를 상속해서 비교 기준을 정하는 클래스를 생성했던 것과 비슷합니다.

function compareNumeric(a, b) {
  if (a > b) 
  		return 1;
  if (a == b) 
  		return 0;
  if (a < b) 
  		return -1;
}

let arr = [ 1, 2, 15 ];

arr.sort(compareNumeric);

a가 첫번째 인수 b가 두번째 인수라고 했을 때 a가 더 크면 양수, b가 더크면 음수를 리턴하도록 로직을 생성하면 됩니다. 이 function을 sort 메서드의 인자로 넘겨주면 해당 function의 로직을 비교기준으로 sorting을 진행하게 되겠습니다.

객체에서든 뭐든 보통 문자열이나 숫자를 비교할텐데 숫자 같은 경우는 그냥 대소 비교를 해 주면 되지만 문자열 같은 경우에는 localeCompare 메서드를 사용하면 특이한 문자열까지 완벽하게 비교해준다고 합니다.

profile
Frontend Developer

0개의 댓글