본문으로 바로가기
JS 중복된 값 제거

제일 직관적인 방법은 새 배열을 준비한 뒤에, 새 배열에 값이 있으면 추가하지 않고 값이 없으면 추가하는 방식이다.

 

function temp(arr:string[]){
    let narr = [] as string[];
    arr.forEach((item)=>{
        if(!narr.includes(item)){
            narr.push(item);
        }
    })
    return narr;
}
console.log(temp(['abc','wtkwltk','qwfokqwof','abc','wkofqpkfwq','김칫국','된장국','김칫국']))

forEach를 사용하든 for(let i = 0; i <...;i++ ) 를 사용하는 방식도 있다.

 

두번쨰는 filter와 includes를 사용하는 방법이다.

function temp2(arr:string[]){
    return arr.filter((item,i)=>arr.indexOf(item)===i);
}

indexOf는 일치하는 가장 첫 인덱스를 반환하기 때문에 해당값을 가진 첫 인덱스들의 배열은 중복된 값을 제거한 배열과 동일하다.

 

세번쨰는 Set 객체를 사용하는 것이다.

function temp3(arr:string[]){
    return [...new Set(arr)];
}

Set 객체 같은 경우에는 유일한 값만을 저장하기 떄문에 Set 객체로 변환하면 중복된 값이 사라지고 이를 비구조화할당을 통해서 다시 배열 형식으로 바꾼다.

 

전자는 중복된 값이 많은 경우, 후자는 중복된 값이 적은 경우의 시간이다.

 

set객체를 통한 중복제거는 처음 알았다.

Associative 같은 경우 알고 있던 것인데 대답하지 못해 아쉽다. 생각하기 어려운 것도 아니었고

 

useLayoutEffect
useLayoutEffect(() => {
  effect
  return () => {
    cleanup
  };
}, [input])

형태는 위와 같다.

 

useLayoutEffect같은 경우의 차이점이라면 useEffect 같은 경우 DOM 레이아웃 배치와 페인트가 끝난후에 호출되는데, 이런 경우 UI적으로 문제가 될 수 있다. 이를 해결하는 것이 useLayoutEffect로 DOM에 그리기 전에 이펙트 함수가 호출된다.

 

useImperativeHandle
useImperativeHandle(ref, createHandle, [deps])

 

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

위와 같은 FancyInput를 렌더링하는 부모 컴포넌트는 inputRef.current.focus()에 접근할 수 있다.

즉 부모에게 자식의 메서드를 넘길수 있는 것이다.

 

부모에게 자식의 메서드를 넘긴다는 것이 리액트의 기본적인 관점과는 다르기 때문에 자주 사용되지는 않을거 같지만 필요한 경우에 사용할 수 있을거 같다.

 

 

나머지 Hooks는 useContext, useCallback, useMemo, useReducer 등은 이미 사용해본 Hooks인데 기억이 안난다고 한게 아쉽다. 찬찬히 생각해볼걸. 애초에 Context API 쓸떄 useContext랑 useReducer를 썼는데 Context API로 구현한 경험을 말하면서 이것들을 생각하지 못한게 아쉽다.

 

힙소트 관련

힙소트도 push와 pop의 시간복잡도가 logn인데, 그거 생각하고 힙정렬의 시간복잡도가 logn라고 했었다...!

조금 더 침착하게 하자. 모르는걸 틀리는건 어쩔수 없지만 아는걸 틀리는건 너무나 뼈아프다.

function heapSort(arr:any){
    let len = arr.length;
    for(let i =Math.floor(arr.length/2); i>=0; i--){
        heapify(arr,i);
    }
    for(let i = len-1; i>0; i--){
        swap(arr,0,i);
        len--;
        heapify(arr,0);
    }
    return arr;
    function swap(arr:any,i:number,j:number){
        let temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    function heapify(arr:any,index:number){
        let max = index;
        let left = 2*index+1;
        let right =2*index+2;

        if(left<len && arr[left]>arr[max]){
            max= left;
        }
        if(right<len && arr[right]>arr[max]){
            max= right;
        }
        if(max!=index){
            swap(arr,index,max);
            heapify(arr,max);
        }
    }
}

let arr = [1,4,5,1,76,5,6,3,5,2];
console.log(heapSort(arr));

힙소트의 시간복잡도는 n개를 logn의 시간복잡도로 반복하니 nlogn지..

 

처음이었으니 아쉬운 부분이 참 많지만, 앞으로 개선해서 면접에 더 잘 임하자

 

내일은 정렬 다시 정리하고 Hash 자료구조 공부하자