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

Flutter:解决向Map列表插入元素时的索引越界问题

问题

我有一个名为products的FireStore集合,文档包含name、price、category等产品数据,结构如下:

[
  {
    "name": "Milk Shake Strawberry",
    "price": "250",
    "category": "Drinks",
    "categoryID": 1234
  },
  {
    "name": "Swiss Roll",
    "price": "150",
    "category": "Cake",
    "categoryID": 1235
  }
]

通过以下代码将产品数据映射为列表:

List<Map<String, dynamic>?>? productItemsData = snapshots.data?.docs
                          .map((e) => e.data() as Map<String, dynamic>?)
                          .toList();

另外还有分类数据,结构如下:

[
  {
    "index": "0",
    "categoryName": "Drinks",
    "categoryID": 1234
  },
  {
    "index": "1",
    "categoryName": "Cake",
    "categoryID": 1235
  }
]

映射分类数据的代码:

List<Map<String, dynamic>?>? categoryData= snapshotCat.data?.docs
                 .map((e) => e.data() as Map<String, dynamic>?)
                 .toList();

之后用两层for循环将产品按分类的index插入到sortedProductItemsData列表中:

for (var doc in categoryData!) {
  Map<String, dynamic> data = doc as Map<String, dynamic>;
  for (var product in productItemsData!) {
    Map<String, dynamic> productData = product as Map<String, dynamic>;
    if (productData["category"] == data["name"]) {
      sortedProductItemsData?.insert(data["index"], productData);
      break;
    }
  }
}

现在遇到的问题是:当要插入的index值大于sortedProductItemsData当前的元素长度时,会抛出错误:

Invalid value: Not in inclusive range 0..5: 8

比如列表仅有2个元素时,尝试插入到索引8的位置就会触发该错误,请问如何避免这个问题?

解决方案

方法1:修正插入索引至有效范围

Dart的List.insert()方法允许插入的索引范围是0到list.length(包含两端),如果目标索引超出这个范围,直接改为插入到列表末尾(即list.length位置)。同时注意将分类数据中的字符串类型index转为整数,避免类型错误。

修改后的代码:

for (var doc in categoryData!) {
  if (doc == null) continue;
  Map<String, dynamic> data = doc as Map<String, dynamic>;
  // 将字符串index转为整数
  int targetIndex = int.parse(data["index"]);
  
  for (var product in productItemsData!) {
    if (product == null) continue;
    Map<String, dynamic> productData = product as Map<String, dynamic>;
    
    if (productData["category"] == data["name"]) {
      if (sortedProductItemsData != null) {
        // 计算合法的插入位置:不超过当前列表长度
        int validIndex = targetIndex <= sortedProductItemsData.length 
            ? targetIndex 
            : sortedProductItemsData.length;
        sortedProductItemsData.insert(validIndex, productData);
      }
      break;
    }
  }
}

方法2:先分组再按分类排序(更高效)

嵌套循环+插入的方式效率较低,且容易出现索引问题,推荐先按分类分组产品,再按分类的index排序后依次拼接:

// 1. 将产品按分类名称分组
Map<String, List<Map<String, dynamic>>> productGroups = {};
for (var product in productItemsData!) {
  if (product == null) continue;
  String category = product["category"];
  productGroups.putIfAbsent(category, () => []).add(product);
}

// 2. 将分类数据按index(整数)排序
categoryData?.sort((a, b) {
  if (a == null || b == null) return 0;
  int indexA = int.parse(a["index"]);
  int indexB = int.parse(b["index"]);
  return indexA.compareTo(indexB);
});

// 3. 按排序后的分类顺序拼接产品列表
List<Map<String, dynamic>> sortedProductItemsData = [];
for (var category in categoryData!) {
  if (category == null) continue;
  String categoryName = category["categoryName"];
  sortedProductItemsData.addAll(productGroups[categoryName] ?? []);
}

额外提示

  • 避免使用强制解包(!),添加空值判断可以减少空指针异常的风险
  • 分类数据中的index是字符串类型,必须转为整数后再排序,否则会出现"10"排在"2"前面的字符串排序错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 04:35:47