LinkedHasMap은 데이터 구조 중 하나이다, Map의 특별한 형태이다.
일반적인 Map은 데이터 입력 하는 순서로 고정되어서 보여진다. 하지만 LinkedHasMap은 자체 Map에 key 값을 가지고 있어서 순서를 바꿀 수 있다. 특히 순회(iteration)나 정렬(sorting)이 필요한 경우 유용하게 사용할 수 있습니다.
LinkedHasMap =key,value
..sort()의 정체
final sortedKeys = groupedExpenses.keys.toList()..sort();
Gpt 답변 :
- groupedExpenses.keys.toList(): groupedExpenses 맵의 키(key)를 리스트로 변환합니다. keys 속성은 맵의 키(key)들을 나타내며, toList() 함수를 호출하여 키들을 리스트로 변환합니다.
- ..sort(): .. 연산자는 "cascade" 연산자로, 동일한 객체에 여러 메서드를 연속적으로 호출할 수 있게 합니다. 이 경우, sort() 메서드를 toList()의 결과인 리스트에 연속해서 호출하므로 리스트를 정렬하는 연산을 수행합니다. 즉, 키들이 정렬됩니다.
정렬된 키 리스트인 sortedKeys에는 이제 groupedExpenses 맵의 키들이 정렬된 순서대로 저장되어 있습니다. 이렇게 정렬된 키 리스트를 사용하여 groupedExpenses 맵을 정렬된 순서대로 순회하거나 처리할 수 있습니다.
정리 : 연속적으로 그룹화 된 groupedExpenses의 key 값들이 리스트로 호출
fromIterable 순회의 정체?
final sortedExpenses = LinkedHashMap.fromIterable(
sortedKeys,
key: (key) => key,
value: (key) => groupedExpenses[key]!,
);
Gpt 답변
위의 코드는 sortedKeys 리스트를 사용하여 groupedExpenses 맵을 정렬된 순서로 다시 만들고, 그 결과를 sortedExpenses에 저장하는 코드입니다.
- LinkedHashMap.fromIterable 메서드를 사용하면 sortedKeys 리스트의 각 항목을 키(key)로 사용하고, 해당 키(key)에 해당하는 groupedExpenses 맵의 값을 값(value)으로 사용하여 새로운 LinkedHashMap을 생성합니다.
- key 파라미터에는 각 항목을 어떻게 키(key)로 사용할지 지정합니다. 여기서는 단순히 key 항목을 그대로 사용하므로 key: (key) => key와 같이 설정합니다.
- value 파라미터에는 각 키(key)에 해당하는 값을 어떻게 추출할지 지정합니다. 여기서는 각 키(key)를 사용하여 groupedExpenses 맵에서 해당 키(key)에 대응하는 값을 추출하고 있으므로 value: (key) => groupedExpenses[key]!와 같이 설정합니다.
결과적으로, sortedExpenses는 sortedKeys 리스트의 순서에 따라 정렬된 키(key) 값을 가지며, 각 키(key)에 해당하는 값을 가지고 있는 LinkedHashMap이 됩니다. 이를 통해 날짜별로 그룹화된 지출 데이터를 정렬된 순서로 접근할 수 있게 됩니다.
정리 : key- groupedExpenses[key] 값을 가지고 해당 순서를 변경할 수 있게 함
적용코드
getxcontroller
LinkedHasMap 코드
해당 코드는 데이터를 가져와서 가공해야 해야하는 코드로 비동기 코드로 작성해야 함
LinkedHasMap 안에 <날짜, List<장부>> groupedExpenses 를 선언
날짜에 date를 넣고, grouedExpenses에 key 값을 부여 그리고 장부를 추가
storedKeys는 groupedExepnese key 값 리스트, 연속적으로 이전 날짜와 비교해서 내림차순으로 하게 함
Future<dynamic> groupExpensesByDate(List<ExpenseRecordItem> expenses) async {
final LinkedHashMap<String, List<ExpenseRecordItem>> groupedExpenses =
LinkedHashMap();
for (final expense in expenses) {
final date =
DateFormat('yyyy-MM-dd').format(DateTime.parse(expense.createdTime));
if (groupedExpenses.containsKey(date)) {
groupedExpenses[date]!.add(expense);
} else {
groupedExpenses[date] = [expense];
}
}
// groupedExpenses의 키(날짜)를 실제 날짜 기반으로 내림차순 정렬
final sortedKeys = groupedExpenses.keys.toList()
..sort((a, b) => DateTime.parse(b).compareTo(DateTime.parse(a)));
final sortedExpenses = LinkedHashMap.fromIterable(
sortedKeys,
key: (key) => key,
value: (key) => groupedExpenses[key]!,
);
return sortedExpenses;
}
UI 코드
LinkedHasMap 코드가 비동기 처리이기 때문에
FutureBuilder 사용, 예외처리 진행해야 함..!
List안에 List를 넣어야 하므로
작은 리스트는 스크롤이 작동안되게 NeverScrollableScrollPhysics()사용
Widget groupedExpensesList(BuildContext context) {
return FutureBuilder<dynamic>(
future: controller.groupExpensesByDate(controller.expenseRecords),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('오류가 발생했습니다.'));
} else if (snapshot.hasData) {
final groupedExpenses = snapshot.data;
final sortedKeys = groupedExpenses.keys.toList();
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: sortedKeys.length,
itemBuilder: (context, index) {
final date = sortedKeys[index];
final expenses = groupedExpenses[date];
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
date, // 날짜 표시
style: const TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: expenses.length,
itemBuilder: (context, itemIndex) {
final expenseRecord = expenses[itemIndex];
return InkWell(
onTap: () {
// 여기에 필요한 동작을 추가하세요.
},
child: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(expenseRecord.name),
Text(
'${expenseRecord.money} 원',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.w600,
color: expenseRecord.isIncome
? Colors.red[300]
: Colors.green,
),
),
],
),
trailing: IconButton(
onPressed: () {
// 여기에 필요한 동작을 추가하세요.
},
icon: const Icon(Icons.delete),
),
),
);
},
),
],
);
},
);
} else {
return Center(child: Text('데이터가 없습니다.'));
}
},
);
}
삭제, 수정 함수를 쓰려니
해당 데이터의 고유한 값을 이용해서 해야 한다고 한다.. 흠
그래서 방법은 밀리단위의 초를 사용하는 것과 uuid 를 사용 하는 것!!!
요것은 내일 해보련다..!!
Flutter 초기에 Map을 공부를 했던 것 같았던 내 기억이
이번 기회에 Map의 간 만 보는 시간이 된 것 같아 기부니 좋다.
일단 날짜 별로 장부 데이터가 잘 입력 되고 있다.
'Flutter-플러터' 카테고리의 다른 글
공공API 사용할 때 한글 깨짐 (0) | 2024.06.18 |
---|---|
path_provider , path 패키지를 이용해서 sqlite 백업 (0) | 2024.02.07 |
Flutter - Gap - SizedBox (0) | 2023.11.07 |
Flutter - supabase (0) | 2023.11.06 |
Flutter 구글 스프레드 시트를 연동하기 2편 (0) | 2023.10.31 |