Dart | Dart #3 Functional Programming

앙두·2023년 7월 8일
0

for My Programming

목록 보기
12/20

Dart : 함수형 프로그래밍

인프런 무료 강의
https://www.inflearn.com/course/lecture?courseSlug=dart-%EC%96%B8%EC%96%B4-%EC%9E%85%EB%AC%B8&unitId=107600
DartPad
https://dartpad.dev/


Funtional Programming

asMap(), toSet(), toList()

// Functional Programming
// List []
// Map {} (key / value)
// Set {} 중복값 x
void main() {
  List<String> blackPink = ['로제', '지수', '리사', '제니', '리사'];

  print(blackPink) // [로제, 지수, 리사, 제니, 리사]
  print(blackPink.asMap()); // {0: 로제, 1: 지수, 2: 리사, 3: 제니, 4: 리사}
  print(blackPink.toSet()); // {로제, 지수, 리사, 제니}
}
  • List 를 형변환 시켜줄 수 있다.
  • asMap()을 사용하면 Map 형태로 변형된다.
  • toSet()을 사용하면 Set형태로 변형된다.
void main() {
  List<String> blackPink = ['로제', '지수', '리사', '제니', '리사'];
  Map blackPinkMap = blackPink.asMap();
  
  print(blackPinkMap); // {0: 로제, 1: 지수, 2: 리사, 3: 제니, 4: 리사}
  print(blackPinkMap.keys.toSet()); // {0, 1, 2, 3, 4}
  print(blackPinkMap.values.toList()); // [로제, 지수, 리사, 제니, 리사]
  
  Set blackPinkSet = Set.from(blackPink);
  
  print(blackPinkSet); // {로제, 지수, 리사, 제니}
}
  • List 형태를 MapasMap() 메서드를 사용하여 담아놓고 사용할 수도 있다.
  • toList()List형태로 변형해준다.
  • 복습 겸, Set은 중복값을 하나로 자동처리 해준다.

methods

void main() {
  List<String> blackPink = ['로제', '지수', '리사', '제니'];

  final sayBlackPink = blackPink.map((el) {
    return '블랙핑크 $el';
  });

  print(blackPink); // [로제, 지수, 리사, 제니]
  print(sayBlackPink); // (블랙핑크 로제, 블랙핑크 지수, 블랙핑크 리사, 블랙핑크 제니)
  print(sayBlackPink.toList()); // [블랙핑크 로제, 블랙핑크 지수, 블랙핑크 리사, 블랙핑크 제니]
  
  // arrow function
  final sayBlackPink2 = blackPink.map((el) => '블랙핑크 $el');
  
  print(sayBlackPink2.toList());
  // [블랙핑크 로제, 블랙핑크 지수, 블랙핑크 리사, 블랙핑크 제니]
}
  • print(sayBlackPink)로 출력하면, Iterable 형태인 ()로 나타난다.
  • toList() 붙여주어 여러 List method를 사용하기 위해 List형태로 변형시킨다
void main() {
  String num = '12345';
  
  final numList = num.split('');
  final numListJpg = numList.map((el) => '$el.jpg').toList();
  
  print(numListJpg); // [1.jpg, 2.jpg, 3.jpg, 4.jpg, 5.jpg]
}

Map 형태를 mapping 하기 (MapEntry)

void main() {
  Map<String, String> myFamily = {
    'Dad': 'John',
    'Mom': 'Amy',
    'Daughter' : 'Ellie',
    'Son' : 'Paul',
  };
  
  final myFamilyRes = myFamily.map((key, value) => MapEntry(
    'I am $key', 'My nams is $value'
  ));
  
  print(myFamily);
  // {Dad: John, Mom: Amy, Daughter: Ellie, Son: Paul}
  print(myFamilyRes);
  // {I am Dad: My nams is John, I am Mom: My nams is Amy, I am Daughter: My nams is Ellie, I am Son: My nams is Paul}
  
  final keys = myFamily.keys.map((k) => '나는 $k').toList();
  final values = myFamily.values.map((v) => '나는 $v').toList();
  
  print(keys);
  // [나는 Dad, 나는 Mom, 나는 Daughter, 나는 Son]
  print(values);
  // [나는 John, 나는 Amy, 나는 Ellie, 나는 Paul]
}
  • Map 형태도 map()을 사용할 수 있다.
  • parameterMap의 구성요소인 keyvalue가 들어간다.
  • iterable()toList()로 변경시킨다.

Set 형태를 mapping 하기

void main() {
  Set blackPinkSet = {
    '제니', '로제', '리사', '지수'
  };
  
  final blackPinkSetRes = blackPinkSet.map((el) => '나는 $el').toSet();
  
  print(blackPinkSetRes); // {나는 제니, 나는 로제, 나는 리사, 나는 지수}
}
  • Set 형태도 map()를 사용할 수 있다.
  • iterable()로 반환하므로, toSet()을 붙여 Set형태로 변형시킨다.

where

void main() {  
  // List 안에 Map 을 넣어준다. 제너릭으로 Type 표시!
  List<Map<String, int>> market = [
    {
      'Strawberry': 1,
      'price': 15000,
    },
    {
      'Cola': 4,
      'price': 2500,
    },
    {
      'Ice-cream': 8,
      'price': 6000,
    },
    {
      'beef': 2,
      'price': 45000,
    }
  ];
  
  // target 이 절대 null이 아님을 (non-nullable) 처리해주기 위해 느낌표(!)를 붙여줌
  final marketPrice = market.where((el) => el['price']! >= 10000).toList();
  
  print(marketPrice); // [{Strawberry: 1, price: 15000}, {beef: 2, price: 45000}]
}
  • where()은 원본을 변경시키지 않고 새로운 것을 반환시킨다.
  • 입력해준 조건이 true인 것들만 filter하여 반환시켜준다.

reduce

void main() {
  List<int> numLi = [1, 10, 3, 8, 2];
  
  final numLiReduce = numLi.reduce((prev, next) {
    print('prev : $prev'); // 처음에만 numLi의 첫 요소인 1
    print('next : $next'); // 10
    print('prev * next : $prev * $next ===> 다음 prev가 됨');
    // 1 * 10 : 10 ===> 다음 prev가 됨
    
    return prev * next;
  });
  
  print(numLiReduce); // 480
 }
  • reduce()는 파라미터로 prev, next 를 넣어준다.
  • prev 에는 return 해주는 값이 축적과 함께 할당이 된다 (처음에 실행시에만, reduce()를 걸어준 List 의 첫요소가 들어감)
  • next는 계속해서 다음 요소가 들어간다
  • ⭐️ reduce를 실행하는 타겟의 type과 똑같은 type을 반환해주어야 한다.
  • Listint타입이라면 reduce의 반환값도 오직 int type 이여야 한다. 아님 에러!
void main() {
  List<String> intro = ['나는', '졸리다', '오늘 빡센 하루', '잘자'];

  final introPhrase = intro.reduce((prev, next) => prev + ' ' + next);

  print(introPhrase); // 나는 졸리다 오늘 빡센 하루 잘자
}

fold

void main() {
  List<int> num = [10, 20, 30, 40];
  
  // type 설정
  // 0 으로 initial value 설정
  final numSum = num.fold<int>(0, (prev, next) => prev + next);
  
  print(numSum); // 100
  
  List<String> str = ['나는', '수박이', '먹고싶어요!'];
  
  final strPhrase = str.fold<String>('', (prev, next) => prev + next);
  
  print(strPhrase); // 나는수박이먹고싶어요!
  
  final strLength = str.fold<int>(0, (prev, next) => prev + next.length);
  
  print(strLength); // 11
}
  • reduce() 와 거의 비슷한데 다르다.
  • fold를 실행하는 타겟의 type 따라가지 않아도 된다.
  • 따로 type을 알아서 설정하여 반환이 가능하다.
  • 첫 파라미터가 initial 값, 초기값이다. (처음에 초기값이 prev에 할당됨)


cascading operator

  • js 로 치면 spread operator 와 동일하다
  • 원본 변경 없이 얕은 복사
void main() {
  List<int> num = [1,2,3,4];
  List<int> num2 = [5,6,7,8];
  
  print([...num, ...num2]); [1, 2, 3, 4, 5, 6, 7, 8]
}

본격적인 Functional Programming

  • json 형태로 데이터를 받으면, class 형으로 변환해서 사용해야 더 편리하다.
  • ListMap, Set 형태로 그대로 사용하면, 내부의 데이터를 명확하게 알 수 없기 때문이다.
  • 여러개 함수들을 chaining 할 수 있다.
  • 데이터 형태를 맘껏 바꿔서 사용할 수 있다.
// class 로 설계도를 만들어준다.
class Market {
  final String name;
  final String price;

  // named parameter
  Market({
    required this.name,
    required this.price,
  });

  
  String toString() {
    return 'Market(name: $name, price: $price)';
  }
}

void main() {
  List<Map<String, String>> market = [
    {
      'name': 'Strawberry',
      'price': '15000',
    },
    {
      'name': 'Cola',
      'price': '2500',
    },
    {
      'name': 'Ice-cream',
      'price': '6000',
    },
    {
      'name': 'Beef',
      'price': '45000',
    }
  ];

  print(market);
  // [{name: Strawberry, price: 15000}, {name: Cola, price: 2500}, {name: Ice-cream, price: 6000}, {name: Beef, price: 45000}]

  // List 에 값이 있는지 없는지 명확히 알 수 없기에 느낌표(!)를 붙여 값이 있음을 증명
  final marketMap = market
      .map((el) => Market(name: el['name']!, price: el['price']!))
      .toList();

  print(marketMap);
  // [Market(name: Strawberry, price: 15000), Market(name: Cola, price: 2500), Market(name: Ice-cream, price: 6000), Market(name: Beef, price: 45000)]
  • json형태로 받은 데이터를 class를 통해, 사용하기 좋게 바꿔주었다.
// 이런식으로 함수 chaining 도 할 수 있다.
  final marketMap = market.map((el) =>
        Market(name: el['name']!, price: el['price']!)).toList()
        .where((el) => el.price == '15000')
        .fold<String>('', (prev, next) => prev + next.name);

  print(marketMap); // Strawberry
profile
쓸모있는 기술자

0개의 댓글