[JS Deep Dive] 배열에서 요소 삭제하기

Kyle Lee·2022년 5월 2일
0

서론

JS의 특유의 자유로운 문법과 여러 강력한 메서드로 인해 배열에서 요소를 삭제할 수 있습니다. 그 다양한 방법들과 사용처에 대해 정리하여 공유하고자 합니다.

다양한 Array 메서드들과 삭제법

  • splice()

배열에서 요소를 삭제하는 가장 기본적인 방법이다.

삭제할 요소의 인덱스를 첫번째 파라미터로 받고 삭제할 요소의 개수를 두번째 파라미터로 받는다. 세번째 파라미터는 optional로 삭제한 요소 대신 넣을 대체값을 받는다.

원본 배열을 변경하는 side effect가 있다.

let array = [1, 2, 3, 4, 5];

// 3번째 요소 하나만 삭제
array.splice(2, 1); // array [1, 2, 4, 5]

// 2번째 요소를 하나 삭제하고 새로운 값 대체
array.splice(1, 1, 3); // array [1, 3, 4, 5]
  • filter()

조건에 따라 배열의 요소를 삭제하며, 조건에 일치한다면 배열 내의 모든 일치값을 제거한다.

각 요소를 순회하며 조건식에 따라 Boolean을 리턴하는 콜백함수를 파라미터로 받는다.

원본 배열을 변경하지 않고 새로운 배열을 리턴한다.

let array = [1, 2, 3, 4, 5, 6];

// 짝수 값만 남기고 나머지를 삭제
let newArray = array.filter((e) => e%2 == 0); // newArray [2, 4, 6]


let sparseArray = [1, , 3, undefined, empty, 6];
// 희소 배열 삭제
let denseArray = sparseArray.filter(e => e !== undefined); // denseArray [1, 3, 6]
  • reduce()

일종의 Selector이면서 Reducer의 역할을 한다.

콜백함수를 첫번째 파라미터로 받으며 해당 함수는 (누적값, 현재 순회 요소, 현재 순회 인덱스, 순회 배열)을 파라미터로 받으며 누적값을 업데이트하고 리턴하는 함수 내부를 구성해서 반환한다.
누적값의 초기값을 두번째 파라미터로 받으며 이는 숫자, 배열, 객체 등 다양한 타입을 설정할 수 있어 자유도가 매우 높다.

원본 배열을 변경하지 않고 새로운 값, 배열 또는 객체를 리턴한다.

let array = [1, 2, 3, 4, 5]

let result = array.reduce((acc, cur, idx, arr) => {
  //누적값에 현재 순회 요소값을 더해주고 
  acc += cur;
  //다음 순회의 누적값으로 반환한다.
  return acc;
  
  //누적값의 초기값으로 0을 설정했다. 생략할 경우 자동으로 순회 배열의 첫번째 요소가 설정된다.
}, 0);
  • delete

배열의 요소를 삭제하지만 length 프로퍼티에는 변화가 없다.
즉, 배열의 요소를 empty 값으로 (undefined) 치환하는 방식으로 요소를 삭제한다.

기존의 Array 메서드과는 다르게 '키워드'로 작동하고 배열을 밀집배열에서 희소배열로 전환한다.

원본 배열의 요소 값을 변경한다.

let array = [1, 2, 3, 4, 5];

delete array[2]; // array [1, 2, empty, 4, 5];

실전 예시

프로그래머스의 코딩 테스트 연습문제 '모의고사'

해당 문제는 각 학생들이 맞춘 정답의 개수를 센 다음 가장 많은 정답을 맞춘 학생을 출력하는 문제입니다.

언뜻 보면 Math.max()를 사용해서 쉽게 답을 구할 수 있을 것 같지만, 같은 수의 정답을 맞춘 경우도 존재하기 때문에 중복 정답 수를 가진 학생을 모두 출력할 수 있어야 합니다.

JS에서 Math.max()는 단순히 가장 높은 값을 보여주지만 이것이 중복이 있는지 혹은 인덱스에 대한 정보는 따로 구해야 합니다.

만약 최고 정답자가 단 한명이라면 indexOf()를 활용할 수 있지만 중복값이 존재한다면 우리는 최대값을 가지고 배열을 순회해서 최대값과 일치하는 값을 다시 새로운 배열에 담아서 리턴하는 for문을 작성해야 합니다.

function solution(answers) {
  const one = [1, 2, 3, 4, 5];
  const two = [2, 1, 2, 3, 2, 4, 2, 5];
  const three = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

  let oneAnswer = answers.filter((e, idx) => e == one[idx%one.length])
  let twoAnswer = answers.filter((e, idx) => e == two[idx%two.length])
  let threeAnswer = answers.filter((e, idx) => e == three[idx%three.length])
    
  let answer = [oneAnswer.length, twoAnswer.length, threeAnswer.length];
  let maxNumb = Math.max(...answer);

  // 단순 for 반복문을 사용한 코드
  let result = [];
  for(let idx = 0; idx < answer.length; idx++){
    if(answer[idx] == maxNumb){
      result.push(idx+1);
    }
  }
  
  // 

  // reduce를 사용하여 Procedural하게 만드는 코드
  let result = answer.reduce((acc, cur, idx) => {
    if(cur == maxNumb) acc.push(idx+1);
    return acc;
  }, [])
  

  return result;
};

acc는 매회 축적되는 값이기 때문에 if문 밖에서 매 순회마다 업데이트 될 수 있도록 작성해야 한다.

profile
필요에 의한 개발

0개의 댓글