[Flutter/Dart] 확장 함수를 사용한 리스트 중복 체크

2021. 9. 13. 10:12Programming/Flutter

반응형

확장 함수를 사용한 리스트 중복 체크

이전에 Map에 확장함수(Extension method)를 만들어보자에서 간단하게 Map의 확장함수 fetch를 만들어서, 널 처리 및 타입 변환 등의 처리를 했었다. 이번에는 확장함수를 사용해서 배열의 중복 체크를 해보자.

결과부터 확인해보자. Dartpad에서 아래의 코드를 돌려보면 정상적으로 값이 출력되는 것을 확인할 수 있다. 간단하지만 자바스크립트로 구현했을때랑은 조금 다른데, 하나씩 살펴보도록 하자.

extension ListExtension<T> on List<T> {
  bool isSameListWith(List<T> other) {
    bool result = true;

    if (length == other.length) {
      asMap().forEach((index, value) {
        if (other[index] != value) {
          result = false;
        }
      });
    } else {
      result = false;
    }

    return result;
  }
}


void main() {
  List<int> listA = [1, 2, 3, 4, 5];
  List<int> listB = [1, 2, 3, 4, 5];
  List<int> listC = [1, 2, 3, 4];
  List<String> listD = ['a', 'b', 'c', 'd'];

  print("listA is same with listB?: ${listA.isSameListWith(listB)}");
  print("listA is same with listC?: ${listA.isSameListWith(listC)}");
  // print("listA is same with listD?: ${listA.isSameListWith(listD)}");
}

asMap()을 사용한 index와 value의 분류

Javascript였다면 collection 메서드의 두 번째 인자가 index이므로, 굳이 이런 절차는 필요하지 않다. 게다가 asMap()을 통해 Map으로 변환하고나면 사용할 수 있는 collection 메서드가 제한되므로, 딱히 편리하지도 않다.

fold를 썼으면 편했을텐데

Map이 지원하는 메서드를 확인하려면 Map을 페이지를 참조하자.

List.asMap()을 사용하면 index를 키로, 리스트의 요소를 값으로 변환하게 된다. 이렇게 index에 대한 접근을 할 수 있다. 먼저 배열의 길이를 체크한다. 배열의 길이가 다르면 당연히 다른 배열이며, 길이를 체크하지 않으면 RangeException이 발생할 수 있으므로 주의하자. (다른 사람들은 모르겠지만 나는 자주 깜빡한다.)

이제 forEach를 통해 서로 다른 배열을 발견하면, 플래그를 false로 변환한다.

제네릭을 사용한 타입 체크

확장함수 선언 시 제네릭을 사용하여 List의 타입과 isSameListWith 메소드에 인자로 전달되는 other의 타입을 T로 고정시켰다. 이 내용은 생략하더라도 런타임에서 각 리스트의 요소를 비교하다 false를 반환하게 된다. 하지만 인자의 타입을 T로 고정시키면 컴파일 타임에 other와 원본 List의 타입을 비교하여 에러를 발생시킨다. 애시당초 List<String>List<int>는 다른 리스트이며, 비교할 이유도 없으니 컴파일 타임에 걸러낼 수 있는 셈이다.

결론

이번에는 확장함수를 통해 두 배열이 서로 다른 리스트인지 체크하고, 나아가서 제네릭을 사용해 타입을 고정시킴으로서 컴파일 타임에 타입과 관련된 에러를 걸러낼 수 있도록 작성해봤다. :)

반응형