[Dart] dart:core 파헤치기 #0

Jinwook Kim·2024년 8월 8일

Dart

목록 보기
2/7
post-thumbnail

dart:core 패키지는 모든 Dart의 기본이 되는 패키지이다. 특별히 import하지 않아도 자동으로 사용할 수 있는 유용한 기능들이 모여있다. 이번 포스트에서는 dart:core에서 필수적으로 알아야 할 기능들을 알아보고자 한다.

1. 숫자 (Numerics)

dart:corenum, int, double 클래스에 대한 기본적인 기능들을 정의하고 있다. 참고로 num 타입은 intdouble 자료형의 부모형이다.

먼저, Stringint로 변환하기 위해 int.parse()를 사용할 수 있다.

int.parse("42"); // 42
int.parse("0x42"); // 66

마찬가지로 Stringdouble로 변환하기 위해서 double.parse()를 쓸 수 있다.

double.parse("0.50"); // 0.5

num에도 num.parse()가 존재하지만, 얘는 String을 적절히 int나, double로 변환시킨다. num으로 변환하지 않는다는 점이 흥미롭다.

num.parse("42"); // 42 (int)
num.parse("0x42"); // 66 (int)
num.parse("0.50"); // 0.5 (double)

만약 진법(Radix)를 특정하고 싶을 때에는, radix 파라미터를 함께 써준다.

int.parse("42", radix: 16); // 66

보다시피, "42"를 넣었지만, 16진법으로 해석하라고 파라미터를 주었기에 결과적으로 66이 반환된다.

반대로, intdoubleString으로 변환하고 싶을 때에는, toString() 메서드를 사용한다.

42.toString(); // "42"
123.456.toString(); // "123.456"

doubleString으로 변환할 시, 자릿수를 한정하고 싶을 때에는, toStringAsFixed()를 사용한다.

123.456.toStringAsFixed(2); // 123.46

2. 문자열 (String)

다트에서 문자열(String)은 UTF-16 코드 유닛의 집합이다. 다트에서 문자열은 불변형이기 때문에, 뒤에서 설명할 모든 메서드는 문자열 자신을 변경시키지 않는다. 또한, 문자열과 정규표현식(Regular Expression)을 이용하여 문자열을 검색하거나 일정 부분을 대치할 수 있다.

문자열이 특정 문자열을 포함하는지 알고 싶다면 contains() 메서드를 사용한다.

"Never odd or even".contains("odd"); // true

문자열이 어떤 다른 문자열로 시작되는지 알고 싶다면, startsWith() 메서드를 사용한다.

"Never odd or even".startsWith("Never"); // true

마찬가지로, 문자열이 어떤 다른 문자열로 끝나는지 알고 싶다면 endsWith() 메서드를 사용할 수 있다.

"Never odd or even".endsWith("even"); // true

문자열의 부분을 가져오고 싶을 때에는, substring() 메서드를 사용한다.

"Never odd or even".substring(6, 9); // "odd"

위의 예에서 주의할 점은, 두번째 파라미터인 9는 포함하지 않는다는 점이다. 즉, 인덱스 6번부터 8번까지 3글자만 가져온다.

trim()을 사용하면 문자열 앞과 뒤의 공백들을 손쉽게 제거할 수 있다.

"   hello     ".trim(); // "hello"

replaceAll() 메서드로 문자열의 특정 부분을 다른 문자열로 대치할 수 있다.

"Hello, NAME!".replaceAll("NAME", "Bob"); // "Hello, Bob!"

반면, replace() 메서드는 첫번째로 등장하는 문자열만을 교체한다는 점을 알아두자.

3. 리스트 (List)

리스트의 맨 뒤에 하나의 아이템을 추가하고 싶을 때에는, add()를 사용한다.

List<String> fruits = ["apples", "oranges"];

fruits.add("kiwis"); // ["apples", "oranges", "kiwis"]

맨 뒤에 여러 개의 아이템을 추가할 때에는, addAll()을 사용하면 된다.

fruits.addAll(["grapes", "bananas"]); // ["apples", "oranges", "grapes", "bananas"]

어떤 아이템의 인덱스를 알고자 할 때에는 indexOf()를 사용한다.

fruits.indexOf("apples"); // 0

리스트를 통째로 비울 때에는, clear()을 사용하면 된다.

fruits.clear(); // []

주의할 점은, clear()는 리스트를 []로 비우는 것이지, 리스트 자체를 없애는 것은 아니라는 점이다.

리스트의 Named Constructor인 filled()를 사용하면 같은 아이템 여러 개를 가지는 리스트를 손쉽게 만들 수 있다.

List<String> vegetables = List.filled(99, "broccoli"); // ["broccoli", …, "broccoli"]

sort()를 사용하여 리스트를 정렬시킬 수 있다.

List<String> fruits = ["bananas", "apples", "oranges"];

fruits.sort(); // ["apples", "bananas", "oranges"]

sort() 안에 파라미터 두 개를 가지는 익명 함수나 람다 함수를 넣으면, 정렬 알고리즘을 커스터마이징할 수 있다. 이때, 함수에서 반환하는 숫자의 부호에 따라 정렬 순서가 정해지게 된다.

fruits.sort((a, b) => a.length - b.length); // ["bananas", "oranges", "apples"]

compareTo() 메서드를 통해서도 정렬 알고리즘 커스터마이징이 가능하다.

fruits.sort((a, b) => a.compareTo(b)); // ["apples", "bananas", "oranges"]

한편, 세트는 다트에서 순서가 정해지지 않은 유일한 값들의 집합이다. 순서가 없기에 인덱스로 아이템을 찾을 수 없다.

세트에도 리스트처럼 addAll(), add(), remove() 등의 메서드가 존재하며 사용법도 완전히 같다. 차이점이라면, 세트에서는 중복값이 자동으로 제거된다.

4. 맵 (Map)

다른 언어에서 Dictionary, 혹은 Hash라고 불리는 맵은, Key-Value 쌍의 순서를 지키지 않는 값들의 집합이다.

맵에서 어떤 키가 있는지 확인하기 위해서는, containsKey()를 사용한다. 마찬가지로 어떤 값이 있는지 확인하기 위해서, containsValue()를 사용할 수 있다.

Map<int, String> nobleGases = {54: "Xenon"};

nobleGases.containsKey(54); // true
nobleGases.containsValue("Xenon") // true

한 쌍의 데이터를 제거하기 위해서는 remove()를 사용할 수 있다. 매개변수로는 키값이 온다.

nobleGases.remove(54); // {}

keys로 전체 키들을, values로 전체 값들을 가져올 수 있다. 이때 반환되는 값은 Iterable 타입이기 때문에, 리스트로 변환하기 위해 toList() 등의 방법이 필요하다.

nobleGases.keys.toList(); // [54, 21, 37]
nobleGases.values.toList(); // ["Xenon", "Xhatrya", "Cysepher"]

5. 컬렉션 (Collection)

리스트, 세트, 맵 등을 모두 통틀어 컬렉션(Collection)이라 부른다. 이 세가지 자료형은 서로 비슷한 점이 많기에, 수많은 메서드와 속성들을 공유한다.

isEmpty로 비어있는지, isNotEmpty로 비어있지 않은지 확인할 수 있다.

List<String> coffees = [];
List<String> teas = ["green", "black", "chamomile", "earl grey"];

coffees.isEmpty; // true
teas.isNotEmpty; // true

where()를 활용하여 값을 필터링할 수 있다.

bool isDecaffeinated(String teaName) => teaName == "chamomile";

teas.where((tea) => isDecaffeinated(tea)); // ["chamomile"]

any()로 적어도 한 아이템이 조건을 만족하는지 확인할 수 있다.

teas.any((tea) => isDecaffeinated(tea)); // true

every()로 모든 아이템이 조건을 만족하는지 확인할 수 있다. 만족하지 않는 아이템이 하나라도 있다면 전체 결과는 false가 된다.

teas.every((tea) => isDecaffeinated(tea)); // false

dart:core에 빌트인되어 있는 기능들은 이것보다 훠얼씬 많다. 모르는 것이 있으면 그때 그때 구글링을 통해 알아보고, 반드시 실습을 통해 자신의 것으로 만들도록 하자.

profile
200 Everything Okay.

0개의 댓글