오늘은 Dart의 List 컬렉션을 알잘딱깔센으로 잘 사용해보기로 하자.
https://api.dart.dev/stable/2.15.1/dart-core/List-class.html
리스트는 데이터를 순차적으로 담을 수 있는 인덱싱 가능한 자료구조이다.
배열을 대체할 수 있다.
서브클래스로 Fixed-length list와 Growable list가 있는데,
말 그대로 Fixed-length list
는 길이가 고정된 list이고,
Growable list
는 아이템에 따라 길이가 조정된다.
보통 아래와 같이 간단하게 사용한다.
Growable list이다.
void main() {
List<int> l = [];
print(l);
}
//result
[]
filled 생성자를 사용하여, 길이와 그 길이를 채울 값을 지정해줄 수 있다.
이때, growable이 false면 (따로 설정하지 않으면 false이다) Fixed-length list,
true이면 Growable list이다.
void main() {
var l1 = List.filled(10, 1, growable : true);
l1.add(3);
print(l1);
var l2 = List.filled(10, 1);
//l1.add(3); Error
//print(l1);
}
//reseult
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3]
empty 생성자를 사용하여, 빈 리스트를 생성할 수 있다.
이때, growable이 false면 (따로 설정하지 않으면 false이다) Fixed-length list,
true이면 Growable list이다.
void main() {
var l1 = List.empty(growable : true);
l1.add(3);
print(l1);
var l2 = List.empty(growable : false);
//l1.add(3); Error
//print(l1);
}
//reseult
[3]
empty 생성자를 사용하여, 빈 리스트를 생성할 수 있다.
이때, growable이 false면 (따로 설정하지 않으면 false이다) Fixed-length list,
true이면 Growable list이다.
void main() {
var l1 = List.empty(growable : true);
l1.add(3);
print(l1);
var l2 = List.empty(growable : false);
//l1.add(3); Error
//print(l1);
}
//reseult
[3]
기타 다른 정보는 공식문서를 확인하자.
https://api.dart.dev/stable/2.15.1/dart-core/List-class.html
자주 쓰이는 것만 정리해보았다.
리스트의 첫번째 원소를 반환한다.
각각 리스트가 비었는지, 비어있지 않은지 확인하여 true/false
를 반환한다.
리스트의 마지막 원소를 반환한다.
리스트의 길이를 반환한다.
마찬가지로 중요하거나 자주 쓰이는 것을 정리해보았다.
리스트 마지막에 원소를 추가한다.
리스트의 원소들을 전부 삭제한다.
void main() {
var l1 = [];
l1.add(1);
l1.add(2);
l1.add(3);
l1.add(4);
l1.clear();
print(l1);
}
//result
[]
리스트 내부 원소들이 value로 순서대로 주어지고, action함수를 반복호출한다.
void main() {
var l1 = [];
l1.add(1);
l1.add(2);
l1.add(3);
l1.add(4);
l1.forEach((value) {print(value);});
}
//result
1
2
3
4
forEach같은 반복문이지만, 이전 함수의 return값을 사용할 수 있다.
initialValue는 시작할 원소의 값이다.
void main() {
List<int> l1 = [];
l1.add(1);
l1.add(2);
l1.add(3);
l1.add(4);
l1.add(5);
l1.add(6);
l1.add(7);
l1.add(8);
l1.add(9);
l1.add(10);
int answer = l1.fold(0, (vTotal, value){
return vTotal + value;
});
print(answer);
int answer2 = l1.fold(1, (vTotal, value){
return vTotal + value;
});
print(answer2);
}
//result
55 //(0(initialValue) + 1 + ... + 10)
56 //(1(initialValue) + 1 + ... + 10)
fold 메소드에서 initialValue가 없는 버전이다.
처음엔 첫번째 원소가 vTotal로 들어오고, 두번째 원소부터 element를 통해 시작된다.
그 이후론 fold
와 같이 이전 return값이 vTotal로 들어온다.
void main() {
List<int> l1 = [];
l1.add(1);
l1.add(2);
l1.add(3);
l1.add(4);
l1.add(5);
l1.add(6);
l1.add(7);
l1.add(8);
l1.add(9);
l1.add(10);
int answer = l1.fold(0, (vTotal, value){
print("vTotal = $vTotal | value = $value");
return vTotal + value;
});
print(answer);
}
//result
vTotal = 1 | value = 2
vTotal = 3 | value = 3
vTotal = 6 | value = 4
vTotal = 10 | value = 5
vTotal = 15 | value = 6
vTotal = 21 | value = 7
vTotal = 28 | value = 8
vTotal = 36 | value = 9
vTotal = 45 | value = 10
55
리스트를 순서대로 접근하면서 가장 처음 만나는 value값을 지운다.
sort함수를 통해 리스트를 정렬할 수 있다.
void main() {
List<int> l1 = [];
l1.add(121);
l1.add(232);
l1.add(3343);
l1.add(14);
l1.add(54);
l1.add(66);
l1.add(74);
l1.add(89);
l1.add(933);
l1.add(44410);
l1.sort();
print(l1);
}
//result
[14, 54, 66, 74, 89, 121, 232, 933, 3343, 44410]
sort함수 매개변수로 compare를 보내면 custom이 가능하다.
void main() {
List<int> l1 = [];
l1.add(121);
l1.add(232);
l1.add(3343);
l1.add(14);
l1.add(54);
l1.add(66);
l1.add(74);
l1.add(89);
l1.add(933);
l1.add(44410);
l1.sort((a, b){return (a > b)? -1:1;});
print(l1);
}
//result
[44410, 3343, 933, 232, 121, 89, 74, 66, 54, 14]
Dart에서는 리스트 이어붙히기가 가능하다
void main() {
var l1 = [1,2,3];
var l2 = [0, ...l1];
var l3 = [0,l1];
print(l1);
print(l2);
print(l3);
}
//result
[1, 2, 3]
[0, 1, 2, 3]
[0, [1, 2, 3]]
Dart에서는 하나의 클래스에 인스턴스 변수 접근, 메소드 호출 등을 한번에 할 수 있다.
공식문서에 따르면, 캐스케이드(.., ?..)를 사용하면 동일한 개체에 대해 일련의 작업을 수행할 수 있습니다. 함수 호출 외에도 동일한 개체의 필드에 액세스할 수도 있습니다. 이렇게 하면 임시 변수를 생성하는 단계를 줄일 수 있고 보다 유동적인 코드를 작성할 수 있습니다.
고 한다.
Before
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
After
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
이처럼 지역변수 사용을 줄일 수 있다.
또한, 경우에 따라 명령어 전체의 길이도 줄일 수 있다.
Before
final addressBook = AddressBookBuilder();
addressBook.name = 'jenny';
addressBook.email = 'jenny@example.com';
addressBook.phone = PhoneNumberBuilder();
addressBook.phone.number = '415-555-0100';
addressBook.phone.label = 'home';
addressBook.phone.build();
addressBook.build();
After
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home').build())
.build();
주의할 점은 오브젝트를 반환하는 함수
에서만 사용이 가능하다.
var sb = StringBuffer();
var returnWrite = sb.write('foo'); //write에서 리턴되는 변수는 없기때문에 1차 문제가 되고
// write함수에서 리턴된 변수의 없는 멤버 write라는 함수에 접근하려고 하니 에러가 발생한다.
returnWrite.write('bar'); //?????
만약 위의 코드를 제대로 사용하려면 아래와 같이 구성하면 된다.
var sb = StringBuffer()
..write('foo')
..write('bar');
https://dart.dev/guides/language/language-tour#cascade-notation-
자주 쓰이는 함수와 유용하게 사용했던 함수들 위주로 정리해보았다.
Dart가 워낙 공식문서를 잘 만들어두긴 했지만, 페이지도 여러 개이며 키워드를 모르면 찾기 힘든 편이다.
가끔씩 이 포스팅처럼 자주쓰는 명령어나 함수를 정리하는 시간도 가져보면 좋을 것 같다.
c++의 container와 비슷하면서도 신기한 기능이 많네요🤭 잘 보고 갑니다!