KooKs

useIsDuplicated

배열 내 중복 여부를 판단하고 관련 유틸을 제공하는 커스텀 훅
ReactTypescript

예시

검사 기준 설정

API

useIsDuplicated<T>(checkList: T[], keyExtractor?: (item: T) => string | number)
  • Parameters
    • checkList (T[])중복 여부를 확인할 배열
    • keyExtractor ((item: T) => string | number)중복 판단을 위한 키를 추출하는 함수 (선택사항)
  • Returns
    • isDuplicated (boolean)배열에 중복된 항목이 있는지 여부
    • isDuplicatedItem (Function)특정 항목이 중복되었는지 확인하는 함수
    • getNoDuplicatedList (Function)중복이 제거된 배열을 반환하는 함수
    • getDuplicatedItems (Function)중복된 항목들의 배열을 반환하는 함수

개발 및 사용환경

ReactTypescript

사용법

1// 기본 사용
2const items = [{ id: 1, name: 'banana' }, { id: 2, name: 'apple' }];
3const { isDuplicated, isDuplicatedItem, getNoDuplicatedList, getDuplicatedItems } = useIsDuplicated(items, (item) => item.id);
4
5// 중복 여부 확인
6console.log(isDuplicated); // false
7
8// 특정 아이템의 중복 여부 확인
9console.log(isDuplicatedItem(items[0])); // false
10
11// 중복이 제거된 배열 가져오기
12const uniqueItems = getNoDuplicatedList();
13
14// 중복된 아이템들 가져오기
15const duplicates = getDuplicatedItems();

Hook

1/**
2 * 배열 내 중복 여부를 판단하고 관련 유틸리티를 제공하는 Hook
3 *
4 * @template T - 배열의 요소 타입
5 * @param {T[]} checkList - 중복 여부를 확인할 배열
6 * @param {KeyExtractor<T>} [keyExtractor] - 중복 판단을 위한 키 추출 함수 (선택적)
7 *
8 * @returns {Object} 중복 관련 유틸리티 객체
9 * @property {boolean} isDuplicated - 배열에 중복된 요소가 있는지 여부
10 * @property {function(T): boolean} isDuplicatedItem - 특정 아이템이 중복되었는지 확인하는 함수
11 * @property {function(): T[]} getNoDuplicatedList - 중복이 제거된 배열을 반환하는 함수
12 * @property {function(): T[]} getDuplicatedItems - 중복된 요소들만 반환하는 함수
13 *
14 * @example
15 * // 기본 사용법 (item 자체를 키로 사용)
16 * const { isDuplicated } = useIsDuplicated([1, 2, 2, 3]);
17 *
18 * @example
19 * // keyExtractor 사용
20 * const { isDuplicated } = useIsDuplicated(
21 *   [{ id: 1 }, { id: 2 }, { id: 2 }],
22 *   (item) => item.id
23 * );
24 */
25function useIsDuplicated<T>(
26  checkList: T[],
27  keyExtractor?: (item: T) => string | number
28) {
29  const getKey =
30    keyExtractor ?? ((item: T) => item as unknown as string | number);
31
32  const { uniqueKeys, duplicates } = useMemo(() => {
33    const seen = new Set<string | number>();
34    const duplicates = new Set<string | number>();
35
36    for (const item of checkList) {
37      const key = getKey(item);
38      if (seen.has(key)) {
39        duplicates.add(key);
40      } else {
41        seen.add(key);
42      }
43    }
44
45    return { uniqueKeys: seen, duplicates };
46  }, [checkList, keyExtractor]);
47
48  const isDuplicated = checkList.length !== uniqueKeys.size;
49
50  const isDuplicatedItem = (item: T) => {
51    const key = getKey(item);
52    let count = 0;
53    for (const i of checkList) {
54      if (getKey(i) === key) {
55        count++;
56        if (count > 1) return true;
57      }
58    }
59    return false;
60  };
61
62  const getNoDuplicatedList = () => {
63    const map = new Map<string | number, T>();
64    for (const item of checkList) {
65      const key = getKey(item);
66      if (!map.has(key)) {
67        map.set(key, item);
68      }
69    }
70    return [...map.values()];
71  };
72
73  const getDuplicatedItems = () => {
74    return checkList.filter((item) => duplicates.has(getKey(item)));
75  };
76
77  return {
78    isDuplicated,
79    isDuplicatedItem,
80    getNoDuplicatedList,
81    getDuplicatedItems,
82  };
83}