首页 > 解决方案 > 有没有办法使用 Dart/Flutter 访问 ForEach 中的索引/键

问题描述

我正在尝试运行以下 foreach 循环,以便删除特定条目。

textMap.results.forEach((element) {
   textMap.results.removeAt(**element.KEY**);
   print(element.KEY)
}

是否可以引用 foreach 循环的索引/键?我已经用一个基本的迭代器对此进行了测试,但是如果列表包含多个需要删除的条目,那么一旦删除了初始项目,索引就会变得不同步。因此,我为什么要寻找索引/键

标签: flutterdartforeachkey

解决方案


首先,避免使用Iterable.forEachexcept for trivial case。如果您想要元素索引,只需使用正常的循环结构(例如for, while)。另请参阅https://stackoverflow.com/a/65420010/

在您的示例代码中,您无条件地删除每个项目,因此您可以List.clear()在最后调用,这将更加简单和高效。那应该是O(1)。

如果您不想删除所有项目,而是需要有条件地删除多个项目,有几种方法可以做到。

  • List.removeWhere尽可能使用。我希望这对于列表的长度是 O(n)。

  • 从最后一个到第一个处理项目,以便从列表中删除元素不会影响迭代:

    for (var i = textMap.results.length - 1; i >= 0; i -= 1) {
      print(textMap.results[i]); // Do something with the element.
      if (shouldRemove(textMap.results[i])) {
        textMap.results.removeAt(i);
      }
    }
    
  • 如果您必须按顺序处理元素,您可以先收集要删除的索引列表,然后单独删除它们:

    var indicesToRemove = <int>[];
    for (var i = 0; i < textMap.results.length; i += 1) {
      print(textMap.results[i]); // Do something with the element.
      if (shouldRemove(textMap.results[i])) {
        indicesToRemove.add(i);
      }
    }
    // Remove in reverse order so that removing items does not affect
    // unprocessed indices.
    for (var index in indicesToRemove.reversed) {
      textMap.results.removeAt(index);
    }
    
  • 或者使用while有条件地增加列表索引的循环:

    var i = 0;
    while (i < textMap.results.length) {
      print(textMap.results[i]); // Do something with the element.
      if (shouldRemove(textMap.results[i])) {
        textMap.results.removeAt(i);
        // Iterate again at the same index.
        continue;
      }
      i += 1;
    }
    

最后三种方法是 O(m*n),其中 n 是列表的长度,m 是要删除的项目数。


推荐阅读