본문 바로가기
flutter/dart

flutter를 위한 dart 기본 문법 (3) - functional programming

by 천뿌니 2022. 11. 30.
728x90

dart

직전 포스팅에서 dart OOP 개념에 대해서 알아보았는데요, 이번에는 dart functional programming 개념에 대해서 알아보겠습니다.

필자는 깊진 않지만 여러 프로그래밍 언어에 대한 경험(컴공)이 있기 때문에 순전히 필자의 기준으로 작성했으니 이 포스트는 프로그래밍 언어를 처음 배우시는 분에겐 맞지 않을 수 있으니 유의!!!

다른 언어를 배워본 경험이 있으신 분들은 가볍게 보시면 dart 문법 금방 아실 거라고 생각합니다.

**음슴체**


형 변환(list, map, set)

 

void main() {
  List<String> blackPink = ['로제', '지수', '리사', '제니', '제니'];
  
  print(blackPink); // => []
  print(blackPink.asMap()); // List -> Map {}
  print(blackPink.toSet()); // List -> Set ()
  
  Map blackPinkMap = blackPink.asMap();
  
  print(blackPinkMap.keys.toList());  // Map keys -> list
  print(blackPinkMap.values.toList()); // Map values -> list
  print(blackPinkMap.keys.toSet()); // Map keys -> set
  print(blackPinkMap.values.toSet()); // Map keys -> set
  
  Set blackPinkSet = Set.from(blackPink); // list -> set
  
  print(blackPinkSet.toList()); // set -> list
}

 

 

list 매핑

void main() {
  List<String> blackPink = ['로제', '지수', '리사', '제니'];
  
  // map을 쓰면 새로운 iterable이 나온다.
  // iterable은 잘 사용하지 않아서 list로 변환해서 자주 사용한다.
  final newBlackPink = blackPink.map((x){
    return '블랙핑크 $x';
  });
  
  print(blackPink);
  print(newBlackPink.toList());
  
  // arrow function 사용 - 간결
  final newBlackPink2 = blackPink.map((x) => '블랙핑크 $x');
  
  print(newBlackPink2.toList());
  
  print(blackPink == blackPink);  // => true
  print(newBlackPink == blackPink); // => false
  print(newBlackPink == newBlackPink2); // => false
  
  // goal : [1.jpg, 3.jpg, 5.jpg, 7.jpg, 9.jpg]
  String number = '13579';
  
  final parsed = number.split('').map((x) => '$x.jpg').toList();
  
  print(parsed);
}

 

 

map 매핑

void main() {
  Map<String, String> harryPotter = {
    'harry Potter': '해리 포터',
    'Ron Weasley': '론 위즐리',
    'Hermione Granger': '헤르미온느 그레인저',
  };
  
  // map 자체를 새로운 map으로 만드는 방법
  final result = harryPotter.map(
    (key, value) => MapEntry(
      'Harry Potter Character $key',
      '해리포터 캐릭터 $value',
    ),
  );
  
  print(harryPotter);
  print(result);
  
  // key, values 값 각각을 맵으로 만드는 방법(리스트로 변환 많이 함)
  final keys = harryPotter.keys.map((x) => 'HPC $x').toList();
  final values = harryPotter.values.map((x) => '해리포터 $x').toList();
  
  print(keys);
  print(values);
}

 

 

set 매핑

리스트와 매우 유사함.

void main() {
  Set blackPinkSet = {
    '로제',
    '지수',
    '제니',
    '리사',
  };
  final newSet = blackPinkSet.map((x) => '블랙핑크 $x').toSet();
  print(newSet);
}

 

 

where

void main() {
  List<Map<String, String>> people = [
    {
      'name' : '로제',
      'group' : '블랙핑크',
    },
    {
      'name' : '지수',
      'group' : '블랙핑크',
    },
    {
      'name' : 'RM',
      'group' : 'BTS',
    },
    {
      'name' : '뷔',
      'group' : 'BTS',
    },
  ];
  
  print(people);
  
  final blackPink = people.where((x) => x['group'] == '블랙핑크');
  final bts = people.where((x) => x['group'] == 'BTS');
  
  print(blackPink);
  print(bts);
}

 

 

reduce

아래 예제를 보면 numbers는 int이기 때문에 result도 int여야 하는 것이다.

void main() {
  List<int> numbers = [
    1,
    3,
    5,
    7,
    9,
  ];
  
  final result = numbers.reduce((prev, next){
    print('--------------');
    print('previous $prev');
    print('next $next');
    print('total : ${prev+next}');
    
    return prev+next;
  });
  
  print(result);

  List<String> words = [
    '안녕하세요 ',
    '저는 ',
    '김아무개입니다.',
  ];
  
  final sentence = words.reduce((prev, next) => prev + next);
  
  print(sentence);

  // 오류 발생 : words는 string인데 length는 int이다. 즉, reduce는 해당 리스트와 같은 타입을 반환해줘야 한다. 
  words.reduce((prev, next) => prev.length + next.length);  // x
}

 

 

fold

fold를 사용해 반환 값의 type을 변경할 수 있다.

void main() {
  List<int> numbers = [1, 3, 5, 7, 9];
  
  // fold : 첫 시작 값 명시
  final sum = numbers.fold<int>(0, (prev, next) => prev + next);
  
  print(sum);
  
  List<String> words = [
    '안녕하세요 ',
    '저는 ',
    '김아무개입니다.',
  ];
  
  final sentence = words.fold('', (prev, next) => prev + next);
  
  print(sentence);

  // fold를 사용해 반환값의 type을 변경할 수 있다.
  final count = words.fold<int>(0, (prev, next) => prev + next.length);  // o
  
  print(count);
}

 

 

cascading operator

void main() {
  List<int> even = [
    2, 4, 6, 8,
  ];
  
  List<int> odd = [
    1, 3, 5, 7,
  ];
  
  // cascading operator : 원하는 값을 펼쳐서 새로운 리스트로 반환
  // ...
  
  print([...even, ...odd]); // => [2, 4, 6, 8, 1, 3, 5, 7]
  print(even == [...even]); // => false
}

 

 

실제 예시 - class와 functional

void main() {
  final List<Map<String, String>> people = [
    {
      'name': '로제',
      'group': '블랙핑크',
    },
    {
      'name': '지수',
      'group': '블랙핑크',
    },
    {
      'name': 'RM',
      'group': 'BTS',
    },
    {
      'name': '뷔',
      'group': 'BTS',
    },
  ];

  print(people);

  final parsedPeople = people
      .map(
        (x) => Person(
          name: x['name']!, // name과 group의 값들이 존재한다는 것을 명시하기 위해 ! 붙임
          group: x['group']!,
        ),
      )
      .toList(); 
// 결과가 Instance of class명 리스트로 나오는데, 이 기본값을 변경하기 위해서 toString의 override
  print(parsedPeople); 

//   for (Person person in parsedPeople) {
//     print(person.name);
//     print(person.group);
//   }

  final bts = parsedPeople.where((x) => x.group == 'BTS');

  print(bts);

   // 와 과정을 한번에 처리 가능
  final result = people
      .map(
        (x) => Person(
          name: x['name']!,
          group: x['group']!,
        ),
      )
      .where((x) => x.group == 'BTS')
      .fold(0, (prev, next) => prev + next.name.length);

  print(result);
}

class Person {
  final String name;
  final String group;

  Person({
    required this.name,
    required this.group,
  });
  
  // 기본값 변경
  @override
  String toString() {
    return 'Person(name:$name, group:$group)';
  }
}

 

 


이번 포스팅은 dart functional programming에 대해 알아보았습니다.

다음 포스팅은 asynchronous programming에 대해 알아보겠습니다. 감사합니다.

댓글