반응형

드디어 스터디 마지막회차.

이번 스터디에서는 Map 심화버전을 다뤄보고자 한다. 

먼저 간단한 예제를 통해 Map과 List를 알아보자.

void main() {
Map map = {
	'Apple' : '사과',
	'Banana' : '바나나',
	'Kiwi' : '키위'
};

	print(map.keys);
	print(map.values);
    
}
(Apple, Banana, Kiwi)
(사과, 바나나, 키위)

Map에서 key값과 value값들을 확인하기 위해선 위와같이 확인할 수 있다.

※물론, print(map['Apple']); 이런형태로도 개별확인은 가능하다.

이번에는 위 map을 List로 변경하려면 어떻게 해야할까?

print(map.keys.toList());
print(map.values.toList());
[Apple, Banana, Kiwi]
[사과, 바나나, 키위]

toList()로 간단하게 List로 변경하여 활용이 가능하다.


이번엔 Map에 entries에 대한 개념에 대해서 익혀보자

Map에 존재하는 entries는 key값과 value값을 셋트로 매핑하여 꺼낼수 있는 기능이라 할수 있다.

아래 예제로 살펴보자.

  Map map = {
    'Apple' : '사과',
    'Banana' : '바나나',
    'Kiwi' : '키위'
  };
  
    final newMap = map.entries.map((entry){
    final key = entry.key;
    final value = entry.value;
    
    return '$key는 한글로 $value 입니다.';
  });
    
  print(newMap);
(Apple는 한글로 사과 입니다., Banana는 한글로 바나나 입니다., Kiwi는 한글로 키위 입니다.)

위 소스에서 entry변수는 인덱스 마다의 key와 value를 담고 있다.

entry.key와 entry.value로 각 인덱스마다 값을 추출할 수 있다.

 

또한 List에서 사용했던 forEach, reduce와 fold도 entries를 이용하면 사용할 수 있다.

reduce와 fold가 기억나지 않는다면, 아래 포스팅 다시 참조!

 

Dart언어공부-25.List 심화 (forEach, map, reduce, fold)

이번 스터디에서는 List심화단계를 다뤄보려 한다. 바로 소스로 확인해 보자. 1. Looping 활용 List world = [ '한국', '중국', '일본', '러시아', '미국' ]; world.forEach((value){ print(value); }); 한국..

masswhale.tistory.com


바로 예제로 확인해보자.

  Map map = {
    'Apple' : '사과',
    'Banana' : '바나나',
    'Kiwi' : '키위'
  };
  
  
    map.entries.forEach((entry){
    final key = entry.key;
    final value = entry.value;
    
    print('$key는 한글로 $value 입니다.');
  
  });
  
  final total = map.entries.fold(0,(vTotal,entry){
    return vTotal + entry.key.length;
    
  });
    
  print(total);
Apple는 한글로 사과 입니다.
Banana는 한글로 바나나 입니다.
Kiwi는 한글로 키위 입니다.
15

위와 같이 entries를 사용하며, forEach와 fold를 무리없이 사용할 수 있다.


Map얘기를 잠깐 떠나,  만약 List에서 index정보까지 받아서 확인하고 싶다면 어떻게 해야할까?

바로 asMap()를 사용하면 된다.

  List<int> numbers = [
    10,
    20,
    30,
    40,
    50,    
  ];
  
  
  final newMap3 = numbers.asMap();
  
  print(newMap3);
{0: 10, 1: 20, 2: 30, 3: 40, 4: 50}

위와같이 List에서 asMap()이라는 간단한 함수를 통해, 자리번호에 따른 값을 확인할 수 있다.

 

여기서 바로 asMap과 entries를 이용하여, 셋트로 추출이 가능하다.

  List<int> numbers = [
    10,
    20,
    30,
    40,
    50,    
  ];
  
    final newMap4 = numbers.asMap().entries.map((entry){
    final index = entry.key;
    final value = entry.value;
    
    return 'index가 $index 일때 값은 $value 입니다.';
  
  });
  
  print(newMap4);
(index가 0 일때 값은 10 입니다., index가 1 일때 값은 20 입니다., index가 2 일때 값은 30 입니다., index가 3 일때 값은 40 입니다., index가 4 일때 값은 50 입니다.)

이렇게 List를 맵으로바꿔서 entries, reduce,fold도 가능하다.

Map과 List를 상황에 따라 서로 바꿔가며 사용을 할수 있다. 

코딩에 정답은 없으니, 언제든 구현하려는 기능에, 상황에 따라 

구현하면 된다.

 

Dart 왕초보 기초 파트 스터디 끝!

반응형
반응형

이번 스터디에서는 List심화단계를 다뤄보려 한다.

바로 소스로 확인해 보자.


1. Looping 활용

  List<String> world = [
    '한국',
    '중국',
    '일본',
    '러시아',
    '미국'
  ];
  
world.forEach((value){
	print(value);
});
한국
중국
일본
러시아
미국

위 소스는 List의 forEach용법이다.

파라미터 자리인 value에 world의 값을 넣어주고, 이 value자리의 파라미터 값을 기능수행 영역에서 사용할 수 있다.

이번에는 forEach와 같은 기능을 수행하는 다른방법을 알아보자.


  List<String> world = [
    '한국',
    '중국',
    '일본',
    '러시아',
    '미국'
  ];
  
for(String value in world){
    print(value);
}
한국
중국
일본
러시아
미국

해당 방식 또한 forEach와 같은 결과를 추출한다.

world의 value값을 String 변수에 넣어, 기능수행 영역에서 사용할 수 있다.

※여기서 말하는 기능수행 영역은 중괄호 안쪽 영역.


2. Mapping - map활용

  List<String> world = [
    '한국',
    '중국',
    '일본',
    '러시아',
    '미국'
  ];
  
final newList = world.map((value){
	return '이 국가명은  ${value}입니다';
});
(이 국가명은  한국입니다, 이 국가명은  중국입니다, 이 국가명은  일본입니다, 이 국가명은  러시아입니다, 이 국가명은  미국입니다)

map의 경우, 기능수행영역 안의 리턴값을 받을 수 있다. 

기능수행영역 안에서 출력(return)할때마다 계속해서 누적 후, newList변수에 신규 할당하기 때문에,

변경된것 처럼 보인다. 하지만, 클래스world의 원값은 변함이 없다.

※ 추가로, 만약 List형태로 바꾸고 싶다면 newList.toList();로 처리할 수 있다.

print(world);
[한국, 중국, 일본, 러시아, 미국]

3. Reduce/Fold - reduce, "fold"

List<int> numbers = [
    0,
    1,
    2,
    3,
    4,
    5,  
];

위 numbers의 값들을 합산해보자.

int total = numbers.fold(0,(vTotal,element){
	return vTotal+element;
});
  
print(total);

첫번째 시작할 값, vTotal은 이전에 리턴해 준 값이다. -> (중괄호(기능수행영역)안에서 반복하면서)

결과값은 15가 추출된다.

15

헷갈릴수 있으니, 중괄호 안에서 수행될때의 값을 보자면 아래와 같이 진행된다고 보면 된다.

  // index = 0
  // element = 0
  // vTotal = 0
  // return = 0 + 0 = 0
  
  // index = 1
  // element = 1
  // vTotal = 0
  // return = 0 + 1 = 1
  
  // index = 2
  // element = 2
  // vTotal = 1
  // return = 1 + 2 = 3
  
  // index = 3
  // element = 3
  // vTotal = 3
  // return 3 + 3 = 6

index는 List값의 자리번호이며, 첫번째 파라미터 0번부터 element자리에 List값을 할당하며 반복된다.

그리고 vTotal 파라미터 자리엔 이전에 리턴받은 결과값이 누적되는 방식이다.


3. Reduce/Fold - "reduce", fold

사용방식은 fold와 큰 차이를 보이지 않는다.

fold에서는 시작값인 0을 지정하는데, reduce에서는 생략된다.

  int total2 = numbers.reduce((vTotal, element){
    //print(vTotal + element);
    return vTotal + element;
  });
print(total3);
15

※여기서 팁

위에 소스를 dart에서는 아래와 같이  간소화가 가능하다.

  int total3 = numbers.reduce((total, element) => total + element);
  print(total3);
15

위 소스에서 보이는 "=>" 이것은 arrow함수라고 한다.

중괄호안에 다양한 기능(계산 등)을 구현하는 것이 아닌, 한줄로 처리하는 간단한 기능이라면

위와 같이 하는 방법도 있다.

 

맨 위에서 다뤘던, world클래스 가지고도 해본다면 아래와 같이 구현할 수 있다.

final newList2 = world.map((value)=> '이 국가명은 $value입니다.');
print(newList2);
(이 국가명은 한국입니다., 이 국가명은 중국입니다., 이 국가명은 일본입니다., 이 국가명은 러시아입니다., 이 국가명은 미국입니다.)

어떤 방식이든 코딩하는데 정답은 없다.

상황에 따라서 유연하게 대응하며 만들어 나가면 되는것이다.

스터디 끝.

반응형
반응형

이번 스터디에서는 다트의 Cascade Operator에 대해서 알아보고자 한다.

이 cascade operator는 간단하다. 바로 소스로 알아보자.

class World {
  String name;
  String group;

  World(
    String name,
    String group,
  )   : this.name = name,
        this.group = group;

  void sayName() {
    print('이 나라의 이름은 ${this.name}입니다.');
  }

  void sayGroup() {
    print('이 나라는 ${this.group}권 입니다.');
  }
}

단순한 클래스 하나를 선언하였다.

이번에는 위 클래스에 대해 인스턴스를 생성하여 호출해보자.

void main() {
	World world = new World('한국', '아시아');
    world.sayName();
    world.sayGroup();

}
이 나라의 이름은 한국입니다.
이 나라는 아시아권 입니다.

여기까진, 기존에 해왔던 클래스생성 -> 인스턴스 생성 후-> 함수호출의 간단한 단계이다.

하지만 dart에서는 이 단계를 간소화 하기 위해, 사용하는 방법이 있는데 이를 cascade operator라 한다.

위 main 함수 안에 쓰여진 인스턴스 생성 , 함수 2개 호출은 아래와같이 간소화 될수 있다.

void main() {
  new World('한국', '아시아')
    ..sayName()
    ..sayGroup();
}
이 나라의 이름은 한국입니다.
이 나라는 아시아권 입니다.

기존에 인스턴스. <- 점 1개 이후에 기능을 호출하여 사용하였지만,

위와같이 인스턴스 생성을 간단하게 줄이며, 함수를 이어서 여러개 사용할때 점2개를 이용한다.

물론 점 3개이상을 사용하여 간소화 하는것이 있으나, 이는 다음 스터디에서 다뤄보겠다.

 

이전 스터디에서도 작성한대로, 코딩에 정답은 없다.

상황에 따라 필요한것을 적절하게..유연하게 사용하여 만드는 것이 중요하다.

dart에서 저렇게 간소화 하여 사용하는 방법도 있다는 것을 알고있는것만으로도 중요하다.

이번 cascade operator스터디 완료.

반응형
반응형

이번 스터디에서는 Dart의 Interface에 대해 다뤄보려 한다.

Interface는 class가 꼭 선언해야(가져야)하는 메소드와 변수를 지정해주는 역할을 한다.

참고로 다른언어에서는 Interface 키워드를 사용하거나, 별도의 파일에 정의하여 상속받아 사용하지만 

dart에서는 일반적인 class처럼 선언해서 사용한다는 차이점이 있다.

바로 소스로 확인해보자.

class WorldInterface{
  String name;
  //이 안에 함수안에 기능을 정의하지 않는다.
  void sayName(){}
}

class Korea implements WorldInterface{
  String name;
  
  Korea(
    String name,
  ):this.name= name;
  
  void sayName(){
    print('이 나라의 이름은 ${this.name}입니다.');
  }
}

class Usa implements WorldInterface{
  String name;
  
  Usa(
    String name,
  ):this.name = name;
  
  void sayName(){
    print('이 나라의 이름은 ${this.name}입니다.');
  }
  
}

 

WorldInterface클래스는 인터페이스의 용도로 사용될 것이기 때문에, 원하는 변수와 함수를 선언만 하고

기능은 정의하지 않는다.

이제 이 인터페이스를 어떻게 사용하느냐면, Korea클래스와 Usa클래스명 옆에 implements 키워드를 작성하고

우측에 WorldInterface를 작성한다.

이때 부턴 Korea클래스와 Usa클래스는 WorldInterface를 구현하고 있기때문에, 반드시 WorldInterface안에있는

변수와 함수를 무조건 선언 및 기능정의를 해야한다.

호출 및 사용은 똑같다.(인스턴스 생성 및 호출)

void main() {
      
  Korea korea = new Korea('한국');
  
  korea.sayName();
  
  Usa usa = new Usa('미국');
  
  usa.sayName();
  
  
}
이 나라의 이름은 한국입니다.
이 나라의 이름은 미국입니다.

이 인터페이스를 왜 사용해야 하는것일까?

인터페이스(Interface)를 사용하는 이유는 비슷한 성격을 가진 class들은 반드시 특정변수와 함수를 가져야 한다라는 

가정이 있을때 인터페이스(Interface)를 사용하면 유용하다.

※이 인터페이스(Interface)를 구현하면, 이 안에 지정된 것들은 모두 강제한다! 라는 것을 의미함.

 

그런데 여기서 하나 드는 의문.

별도의 Interface키워드를 사용하지 않는다면, 일반 클래스처럼 extends로 사용해도 되지않나? 아래처럼?

class Asia{
  final String name;
  
  Asia(
    String name,
  ):this.name = name;

  void sayName(){}
  
}


class Japan extends Asia{
  
  Japan(
    String name,
  ):super(
    name=name
  );

  @override
  void sayName(){
    print('이 나라의 이름은 ${this.name}입니다.');
  
  }
  
}

물론 소스상으로 봤을때나, 출력하는 형태에 대해서는 큰 차이는 없어보이지만

분명히 성격이 다르다. 

상속은 부모의 모든 값을 그대로 이어받아서 (위 소스기준으로) sayName을 한번더 

선언하지 않아도 (재사용-오버라이드-덮어쓰기) 되지만, 인터페이스의 경우 반드시 내가 가지고 있는 변수와 함수를

선언해라! 라는 강제의 의미가 들어있다.

어느것이든 정답은 없다.

상황에 따라 상속이나 구현을 (extends or interface) 사용하여 유연하게 코딩을 하고 프로그램을 만들어 나가면 된다. 

다만, 해당 변수와 함수가 강제되는 클래스를 만들고 싶다면, 상속보단 구현이 맞다고 본다.

오늘의 스터디 끝!

반응형

+ Recent posts