본문 바로가기

CS/Flutter | Dart

Dart Functional Programming - map, set, reduce, fold

void main() {
  List<String> blackPink = ["로제", "제니", "리사", "지수", "제니"];
  
  print(blackPink);
  print(blackPink.asMap());
  print(blackPink.toSet());
}

List를 map으로 해주면 {0: 로제, 1: 제니, 2: 리사, 3: 지수, 4: 제니}

set으로 해주면 {로제, 제니, 리사, 지수} 

제니가 중복으로 2개 있었는데 set은 중복 제거된 것 볼 수 있음

 

 

void main() {
  List<String> blackPink = ["로제", "제니", "리사", "지수", "제니"];
  
  Map bpMap = blackPink.asMap();
  print(bpMap.keys);
  print(bpMap.values);
  
  print("-"*20);
  
  print(bpMap.keys.toList());
  print(bpMap.values.toList());
}

(0, 1, 2, 3, 4)
(로제, 제니, 리사, 지수, 제니)
--------------------
[0, 1, 2, 3, 4]
[로제, 제니, 리사, 지수, 제니]

 

List로 변환하기 유용하지만 자주 사용하진 않는다고 함

 

 

void main() {
  List<String> blackPink = ["로제", "제니", "리사", "지수", "제니"];
  
  Set bpSet = Set.from(blackPink);
  print(bpSet.toList());
}

요거는 Set

 

 

void main() {
  List<String> blackPink = ["로제", "제니", "리사", "지수"];
  
  final newBP = blackPink.map((x){
    return "블랙핑크 $x";
  });
  
  print(blackPink);
  print(newBP);
}

[로제, 제니, 리사, 지수]
(블랙핑크 로제, 블랙핑크 제니, 블랙핑크 리사, 블랙핑크 지수)

 

x 앞에 '블랙핑크'가 붙어 출력

map 함수 이용해 새로운 newBP List를 만들어줬기에 원래 blackPink List는 바뀌지 않음

 

 

void main() {
  List<String> blackPink = ["로제", "제니", "리사", "지수"];
  
  final newBP = blackPink.map((x){
    return "블랙핑크 $x";
  });
  print(blackPink);
  print(newBP.toList());
  
  print("-"*20);
  
  final newBP2 = blackPink.map((x) => "블랙핑크 $x");
  print(newBP2.toList());
}

final newBP2 = blackPink.map((x) => "블랙핑크 $x");

arrow function 이용하면 위와 같이 간략히 나타낼 수 있음

 

 

void main() {
  String num1 = "12345";
  final parsed = num1.split("").map((x) => "$x.jpg").toList();
  print(parsed);
}

[1.jpg, 2.jpg, 3.jpg, 4.jpg, 5.jpg]

이런 식으로 자주 사용

 

 

map 자체를 mapping해 새로운 map 만들기

void main() {
  Map<String, String> harryPotter = {
    "Harry": "해리",
    "Ron": "론",
    "Hermione": "헤르미온느"
  };

  final res = harryPotter.map(
    (key, value) => MapEntry(
      "Character $key",
      "캐릭터 $value",
    ),
  );

  print(harryPotter);
  print(res);
}

 

{Harry: 해리, Ron: 론, Hermione: 헤르미온느}
{Character Harry: 캐릭터 해리, Character Ron: 캐릭터 론, Character Hermione: 캐릭터 헤르미온느}

 

위 예시처럼은 자주 안쓰고

 

 

map의 key값/value값을 list형태로 바꾸기

void main() {
  Map<String, String> harryPotter = {
    "Harry": "해리",
    "Ron": "론",
    "Hermione": "헤르미온느"
  };

  final keys = harryPotter.keys.map((x) => "Character $x").toList();
  print(keys);
}

[Character Harry, Character Ron, Character Hermione]

 

이렇게 많이 씀

value 값도 당연히 가능

 

 

Set도 마찬가지

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

{블랙핑크 로제, 블랙핑크 제니, 블랙핑크 지수, 블랙핑크 리사}

 

 

where

void main() {
  List<Map<String, String>> ppl = [
    {
      "name": "로제",
      "group": "블랙핑크",
    },
    {
      "name": "지수",
      "group": "블랙핑크",
    },
    {
      "name": "뷔",
      "group": "bts",
    },
    {
      "name": "제이홉",
      "group": "bts",
    },
  ];
  
  print(ppl);
  
  final bp = ppl.where((x) => x["group"] == "블랙핑크").toList();
  final bts = ppl.where((x) => x["group"] == "bts").toList();
  
  print(bp);
  print(bts);
}

[{name: 로제, group: 블랙핑크}, {name: 지수, group: 블랙핑크}, {name: 뷔, group: bts}, {name: 제이홉, group: bts}]
[{name: 로제, group: 블랙핑크}, {name: 지수, group: 블랙핑크}]
[{name: 뷔, group: bts}, {name: 제이홉, group: bts}]

 

 

reduce

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];

  final res = numbers.reduce((prev, next) {
    print("-" * 20);
    print("prev: $prev");
    print("next: $next");
    print("total: ${prev + next}");
    return prev + next;
  });

  print(res);
}

--------------------
prev: 1
next: 2
total: 3
--------------------
prev: 3
next: 3
total: 6
--------------------
prev: 6
next: 4
total: 10
--------------------
prev: 10
next: 5
total: 15
15

 

prev에는 이전까지의 total값이, next에는 list의 다음 값이 들어가 계산됨

 

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];

  final res = numbers.reduce((prev, next) => prev + next);
  print(res);
}

이렇게 arrow 이용해도 똑같은 결과 값(15) 나옴

 

 

void main() {
  List<String> words = [
    "안녕하세요 ", "저는 ", "다미입니다.",
  ];
  
  final sentence = words.reduce((prev, next) => prev + next);
  print(sentence);
}

안녕하세요 저는 다미입니다.

이런 식으로 쓸 수 있음

 

reduce는 reduce를 실행하는 list의 멤버 타입과 같은 타입을 리턴해줘야지만 사용 가능

 

 

fold

reduce와 fold는 비슷한 기능을 수행하지만 fold는 list의 멤버 타입과 다른 타입도 사용 가능

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];

  final res = numbers.fold<int>(0, (prev, next) {
    print("-" * 20);
    print("prev: $prev");
    print("next: $next");
    print("total: ${prev + next}");
    return prev + next;
  });

  print(res);
}

--------------------
prev: 0
next: 1
total: 1
--------------------
prev: 1
next: 2
total: 3
--------------------
prev: 3
next: 3
total: 6
--------------------
prev: 6
next: 4
total: 10
--------------------
prev: 10
next: 5
total: 15
15

 

fold는 지정해 준 0이  가장 첫 prev로 들어가고 list의 next(위 예제에서는 1)이 들어감

이후는 reduce와 같게 동작

 

 

void main() {
  List<String> words = [
    "안녕 ", "나는 ", "다미!",
  ];
  
  final sentence = words.fold<String>("", (prev, next) => prev + next);
  print(sentence);
  
  final cnt = words.fold<int>(0, (prev, next) => prev + next.length);
  print(cnt);
}

안녕 나는 다미!
9

 

fold 사용하면 reduce에서는 못했던 length값 더해주기도 가능

(reduce 예시에서는 String으로 받은 값과 리턴 값 타입이 같아야(String) 했지만, fold 에서는 String으로 받았어도 리턴 값을 <int> 이런 식으로 제너릭 이용해 해주면 가능

 

 

 


Tiny Star