본문 바로가기

Flutter-플러터

음식점 사장님 장부 앱 Test Code 3 : LinkedHasMap

반응형

 

LinkedHasMap은 데이터 구조 중 하나이다, Map의 특별한 형태이다. 

일반적인 Map은 데이터 입력 하는 순서로 고정되어서 보여진다. 하지만 LinkedHasMap은 자체 Map에 key 값을 가지고 있어서 순서를 바꿀 수 있다. 특히 순회(iteration)나 정렬(sorting)이 필요한 경우 유용하게 사용할 수 있습니다.

 

LinkedHasMap =key,value 

 

..sort()의 정체 

final sortedKeys = groupedExpenses.keys.toList()..sort();

 

Gpt 답변 : 

  1. groupedExpenses.keys.toList(): groupedExpenses 맵의 키(key)를 리스트로 변환합니다. keys 속성은 맵의 키(key)들을 나타내며, toList() 함수를 호출하여 키들을 리스트로 변환합니다.
  2. ..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에 저장하는 코드입니다.

  1. LinkedHashMap.fromIterable 메서드를 사용하면 sortedKeys 리스트의 각 항목을 키(key)로 사용하고, 해당 키(key)에 해당하는 groupedExpenses 맵의 값을 값(value)으로 사용하여 새로운 LinkedHashMap을 생성합니다.
  2. key 파라미터에는 각 항목을 어떻게 키(key)로 사용할지 지정합니다. 여기서는 단순히 key 항목을 그대로 사용하므로 key: (key) => key와 같이 설정합니다.
  3. 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의 간 만 보는 시간이 된 것 같아 기부니 좋다. 

 

일단 날짜 별로 장부 데이터가 잘 입력 되고 있다. 

 

728x90
반응형