TIL: 2022-05-19 split, splice, slice

김하연·2022년 5월 19일
0

TIL: Today I Leaned

목록 보기
10/25

오늘의 할 일




오늘 물음표 500개 뜨게 만들었던 splice에 대한 의문

오늘은 알고리즘 시험을 보는 날이었는데, 시험을 보다가 splice의 늪에 빠져버렸다...
splice를 실행할 경우 반환값이 어떤 경우에는 삭제된 요소가 나오고, 또 다른 경우에는 삭제된 요소를 제외한 나머지가 나오길래 너무 헷갈려서 한 번 정리하고 넘어가야 할 필요가 있을 것 같았다.
그래서 시험이 끝나고 테스트를 위한 코드를 작성해보았다.
근데 테스트 코드의 결과값이 내가 예상한대로 나오지가 않아서... 그 이유를 혼자 머리싸매고 엄청 고민하다가 결국 도움을 받아 이해한 내용을 정리해보았다.




1. 이 문제에 의문을 가지기 전에 내가 미리 이해하고 있던 개념

  • 원본 array에 splice를 이용해 요소를 제거하면, 원본 array에서는 제거된 값이 사라진다.
ex) let a = [1,2,3,4,5];
	a.splice(0,1) >> a에는 [2,3,4,5] 만 남음
  • 원본 array에 splice 적용한 것을 다른 변수에 담으면, 그 변수에는 제거된 값만 저장된다.
    (splice의 반환값은 제거된 대상이기 때문에)
ex) let a = [1,2,3,4,5];
	let b = a.splice(0,1) >> b = [1];

2. splice의 반환값을 확인하기 위해 작성한 테스트 코드

    let test_1 = function(){
      let arr = ["AA", "BB", "CC", "DD", "EE"];
      arr.splice(0, 1);
      return arr;
    }

    let test_2 = function(){
      let arr = ["AA", "BB", "CC", "DD", "EE"];
      return arr.splice(0, 1);
    }

    let test_3 = function(){
      let arr = ["AA", "BB", "CC", "DD", "EE"];
      let newArr = [];
      return newArr = arr.splice(0, 1);
    }

    let test_4 = function(){
      let arr = ["AA", "BB", "CC", "DD", "EE"];
      for(let i=0; i<arr.length; i++){
        arr[i].split('').splice(0,1).join('');
      }
      return arr;
    }
    
    console.log(test_1(), 'test_1') // ["BB", "CC", "DD", "EE"]
    console.log(test_2(), 'test_2') // ["AA"]
    console.log(test_3(), 'test_3') // ["AA]
    console.log(test_4(), 'test_4') // ["AA", "BB", "CC", "DD", "EE"]

3. 그리고 생긴 의문...

  • [문제 1] test_2 의 결과가 test_1 이랑 같을 줄 알았는데 왜 다르지..?

  • [문제 2] 4번은 기존 array를 새로운 배열에 저장해서 리턴한게 아니고 기존 array에서 각 요소의 첫번째 글자들을 제거한 후 반환했는데, 왜 기존 array가 수정되지 않았지..?

4번 기대한 결과: ["A", "B", "C", "D", "E"]
4번 실제 반환된 결과 : ["AA", "BB", "CC", "DD", "EE"] (기존 배열 그대로)

4. 해결 과정 (feat.전 직장 동료)

혼자 아무리 머리를 굴려봐도 도저히 이해가 안되길래... ㅠㅠ
퇴근 30분을 남겨둔 전 직장 프론트엔드 친구에게 다짜고짜 연락해서..? 답답해서 죽을 것 같은 문제가 생겼는데 제발좀 봐달라고 부탁을 했다..ㅋㅋㅋㅋㅋㅋㅋ
작성한 코드와 의문점을 보여주자마자 '이걸 묻는다고?' 라는 반응이었지만.. 그래도 내 수준에 맞춰서 친절히 설명해준 나의 구세주..... 감사합니다..


> test_1
test_1의 경우를 컴퓨터에게 하는 나의 요청사항이라고 생각한다면,

나: "arr에서 0번째 index에 있는 요소 1개 빼줘"
=> 컴퓨터 : arr에서 0번째 요소 삭제
나: "그 arr 돌려줘"
=> 컴퓨터 : 0번째 요소 삭제한 arr 반환

위와 같기 때문에 당연히 첫 번째 요소가 제거된 상태의 배열이 반환됐다.
여기까진 이해했는데, test_2의 결과는 왜 test_1과 같지 않은지가 의문이었다.

> test_2

나: "arr 안에서 0번째 index에 있는 요소 1개 빼서 돌려줘"
=> 컴퓨터 : arr로부터 제거된 0번째 요소인 "AA"를 반환

나는 test_1과 test_2가 arr.splice(0,1)을 그냥 미리 실행하고 나중에 리턴을 하느냐, 아님 아예 리턴하는 곳에서 arr.splice(0,1)를 바로 해서 내보내느냐의 차이인 줄 알았고, 그래서 둘은 같은 값이 나올거라고 생각했다. 근데 반환 요청을 어떻게 하느냐에 따라 반환되는 값이 아예 달라진다는걸 깨달았다.. 한끗 차이 같은데 결과는 이렇게나 다르다니 ㅠㅠ

ㅋㅋㅋ진짜 개떡같은 질문을 해도 찰떡같은 설명해주는 클라쓰...
무작정 혼자 이해부터 하려고 했을 땐 전~~~혀 이해가 안됐는데, 내가 진짜 컴퓨터한테 요청하는 것처럼 글로 써서 알려주니까 죽어도 이해 안되던 게 바로 이해가 됐다.

> test_4
그럼 test_4에서는 arr[i] 요소들에서 0번째 인덱스 삭제하라는 요청도 미리 했고, 그 후에 그 arr를 반환해달라고 요청했는데 왜 수정되지 않은 원본 arr가 반환될까...?
이거는 arr[i]를 split 하는 행위에서부터 잘못됐다고 한다..ㅎㅋㅋㅋ.....

arr[i]에 split을 요청하더라도 원본인 arr[i]는 변하지 않고, split된 값을 일단 연산하는 곳에 저장해었다가 쓰는거라고 한다.

실제로 그 과정을 콘솔에 찍어서 테스트해보니 정말 원본 텍스트는 split의 영향을 전혀 받지 않은것을 볼 수 있다.
그래서, 내가 원하는 바를(?) 이루려면, 아래처럼 수정을 해야한다.

 let test_4 = function(){
      let arr = ["coke", "water", "glass", "dog", "dog", "yogurt", "vitamin"];
      for(let i=0; i<arr.length; i++){
        arr[i] = arr[i].split('');
        arr[i].splice(0,1);
        arr[i] = arr[i].join('');
      }
      return arr;
    }
  1. 우선 arr[i]를 split한 값을 arr[i]에 다시 저장한다.
  2. 그 후 split이 적용된 arr[i]에 splice 하라는 요청을 내린다.
  3. splice로 인해 변경된 상태의 arr[i]를 다시 join('')으로 합친다.
    join도 원본 배열을 변화시키지 않기 때문에 join한 값을 arr[i]에 다시 넣어주는 것이다.

아니면, splice에 대한 집착을 버리고 slice를 활용해도 된다. (더 간단...)

let test_4 = function(){
      let arr = ["coke", "water", "glass", "dog", "dog", "yogurt", "vitamin"];
      for(let i=0; i<arr.length; i++){
        arr[i] = arr[i].slice(1);
      }
      return arr;
    }

slice도 원본 배열은 바꾸지 않기 때문에 split 처럼 다시 원본에 담아줘야 잘린 후의 값이 저장된다.


휴우.. 이렇게 이해하고 해결하고 나니까 마치 이틀동안 체해있던 무언가가 쑥 내려가는 느낌이었다.
계속 애매하게만 알고있던 개념을 제대로 잡은 느낌...!!!!
그리고 텍스트 자를 때 맨날 splice가 먼저 떠올라서 굳이 텍스트를 split으로 나누고 splice 적용하는 방식을 사용했었는데, 텍스트에 바로 적용이 가능한 slice를 앞으로 더 활용해봐야겠다.




splice(), split(), slice() 정리

  • splice()
    대상이 되는 배열을 자르거나, 요소를 새로 추가해줄 수 있음.
    대상이 되는 배열도 변하고, 반환값은 잘린 요소들만 반환한다.

  • split()
    split('구분문자') 구분문자를 기준으로 요소를 나누어준다.
    구분문자를 넣지 않을 경우 그냥 모든 요소를 다 떼어버린다.
    split으로 잘린 결과값은 연산하는 곳 어딘가에 저장돼있기 때문에 split 대상에는 변화가 없다.

  • slice()
    slice도 split과 같이 결과값은 연산하는 곳 어딘가에 저장돼있기 때문에 slice 대상에는 변화가 없다.

0개의 댓글