You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart列表去重分组及运算符[]未定义错误解决求助

Dart数据分组转换问题及解决

原始数据

我有如下Dart Map列表数据:

[
   {
      "ExtendedDutyId":1,
      "DutyName":"Overtime duties",
      "DutyDate":"2022-10-26",
      "FromTime":"0:00",
      "ToTime":"36:00",
      "Allowance":0,
      "ShiftType":-1,
      "ShiftCode":-1,

      "Employee":{
         "EmployeeId":1025,
         "FirstName":"Daniel",
         "LastName":"Hansen-Hansen",
         "CompanyCode":"BY"
      }
   },
   {
      "ExtendedDutyId":1,
      "DutyName":"Overtime duties",
      "DutyDate":"2022-10-26",
      "FromTime":"5:11",
      "ToTime":"10:29",
      "Allowance":0,
      "ShiftType":-1,
      "ShiftCode":1314679,
      "Employee":{
         "EmployeeId":1025,
         "FirstName":"Daniel",
         "LastName":"Hansen-Hansen",
         "CompanyCode":"BY"
      }
   },
   {
      "ExtendedDutyId":1,
      "DutyName":"Overtime duties",
      "DutyDate":"2022-10-27",
      "FromTime":"0:00",
      "ToTime":"36:00",
      "Allowance":0,
      "ShiftType": -1,
      "ShiftCode":-1,
      "Employee":{
         "EmployeeId":1025,
         "FirstName":"Daniel",
         "LastName":"Hansen-Hansen",
         "CompanyCode":"BY"
      }
   }
]

目标结构

希望将上述数据处理后得到如下结构(注:原描述中“按DateOfBirth分组”应为笔误,实际为按员工分组并转换时间格式):

{
   "employeeTimeRegStatus":[
      {
         "supervisor":1035,
         "employeeId":1025,
         "companyCode":"BY",
         "statusId":1,
         "timeRegs":[
            {
               "ExtendedDutyId":1,
               "DutyName":"Overtime duties",
               "DutyDate":"2022-10-26",
               "FromTime":0,
               "ToTime":2160,
               "ShiftType":-1,
               "ShiftCode":-1,
               "Allowance":0
            },
            {
               "ExtendedDutyId":1,
               "DutyName":"Overtime duties",
               "DutyDate":"2022-10-27",
               "FromTime":0,
               "ToTime":2160,
               "ShiftType":-1,
               "ShiftCode":-1,
               "Allowance":0
            },
            {
               "ExtendedDutyId":1,
               "DutyName":"Overtime duties",
               "DutyDate":"2022-10-26",
               "FromTime":311,
               "ToTime":629,
               "ShiftType":-1,
               "ShiftCode":1314679,
               "Allowance":0
            }
         ]
      }
   ]
}

遇到的错误

尝试代码时出现如下错误:

The operator '[]' isn't defined for the class 'Object?'

尝试的代码

final value = xdata.fold(Map<String, List<dynamic>>(), 
   (Map<String, List<dynamic>> a, b) {
       a.putIfAbsent(b["Employee"]!["FirstName"].toString(), () 
         => []).add(b);
           return a;
         }).values
            .where((l) => l.isNotEmpty)
            .map((l) => {
   
            'Supervisor': l.first["Supervisor"],
            'employeeId': l.first["employeeId"],
            'companyCode': l.first["companyCode"],
            'statusId': l.first["statusId"],

            'TimeRegs': l.map((e) => {
            'ExtendedDutyId': e['ExtendedDutyId'],
            'DutyName': e['DutyName'],
            'DutyDate': e['DutyDate'],
            'FromTime': e['FromTime'],
            'ToTime': e['ToTime'],
            'ShiftType': e['ShiftType'],
            'ShiftCode': e['ShiftCode'],
            'Allowance': e['Allowance'],
          }).toList()
        }).toList();

相关模型类

class EmployeeTimeRegStatus {
      int? supervisor;
      int? employeeId;
      String? companyCode;
      int? statusId;
      List<TimeRegs>? timeRegs;

   EmployeeTimeRegStatus(
         {this.supervisor,
         this.employeeId,
         this.companyCode,
         this.statusId,
         this.timeRegs});}

问题分析与解决

错误原因

  1. 类型推断问题:b["Employee"]返回Object?类型,直接使用[]操作符会触发类型错误,需明确转换为Map类型。
  2. 字段匹配错误:原始数据中没有Supervisor、employeeId、companyCode、statusId这些顶层字段,需从Employee子Map中获取对应字段,statusId和supervisor为固定值。
  3. 时间格式未转换:目标结构要求将FromTime/ToTime的字符串格式转换为分钟数,原代码未处理该逻辑。

修正后的代码

首先补充TimeRegs模型类:

class TimeRegs {
  int? extendedDutyId;
  String? dutyName;
  String? dutyDate;
  int? fromTime;
  int? toTime;
  int? shiftType;
  int? shiftCode;
  int? allowance;

  TimeRegs({
    this.extendedDutyId,
    this.dutyName,
    this.dutyDate,
    this.fromTime,
    this.toTime,
    this.shiftType,
    this.shiftCode,
    this.allowance,
  });
}

然后是数据处理核心代码:

// 辅助函数:将"小时:分钟"格式字符串转换为总分钟数
int convertTimeToMinutes(String timeStr) {
  final parts = timeStr.split(':');
  if (parts.length != 2) return 0;
  final hours = int.tryParse(parts[0]) ?? 0;
  final minutes = int.tryParse(parts[1]) ?? 0;
  return hours * 60 + minutes;
}

// 处理数据并转换为目标模型
List<EmployeeTimeRegStatus> processData(List<Map<String, dynamic>> xdata) {
  // 按员工ID分组(比姓名更可靠,避免重名)
  final groupedData = <int, List<Map<String, dynamic>>>{};

  for (final item in xdata) {
    final employee = item["Employee"] as Map<String, dynamic>;
    final employeeId = employee["EmployeeId"] as int;
    groupedData.putIfAbsent(employeeId, () => []).add(item);
  }

  // 转换为目标模型列表
  return groupedData.entries.map((entry) {
    final employeeId = entry.key;
    final items = entry.value;
    final firstEmployee = items.first["Employee"] as Map<String, dynamic>;
    final companyCode = firstEmployee["CompanyCode"] as String;

    // 转换timeRegs列表
    final timeRegs = items.map((item) {
      return TimeRegs(
        extendedDutyId: item["ExtendedDutyId"] as int,
        dutyName: item["DutyName"] as String,
        dutyDate: item["DutyDate"] as String,
        fromTime: convertTimeToMinutes(item["FromTime"] as String),
        toTime: convertTimeToMinutes(item["ToTime"] as String),
        shiftType: item["ShiftType"] as int,
        shiftCode: item["ShiftCode"] as int,
        allowance: item["Allowance"] as int,
      );
    }).toList();

    return EmployeeTimeRegStatus(
      supervisor: 1035, // 固定值,可根据业务逻辑调整来源
      employeeId: employeeId,
      companyCode: companyCode,
      statusId: 1, // 固定值,可根据业务逻辑调整来源
      timeRegs: timeRegs,
    );
  }).toList();
}

// 使用示例
// final processedList = processData(yourOriginalDataList);

代码说明

  1. 明确类型转换:将item["Employee"]强制转换为Map<String, dynamic>,解决Object?类型无法使用[]的问题。
  2. 可靠分组逻辑:改用员工ID作为分组键,避免姓名重复导致的分组错误。
  3. 时间格式转换:通过辅助函数将时间字符串转换为分钟数,匹配目标结构要求。
  4. 类型安全映射:直接映射到定义好的模型类,避免动态Map的类型风险。

内容的提问来源于stack exchange,提问作者Arslan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:30:38