枚举或映射Dart中具有索引和值的列表

Dav*_*ees 31 dart flutter

在dart中,有任何等同于普通的东西:

enumerate(List) -> Iterator((index, value) => f)
or 
List.enumerate()  -> Iterator((index, value) => f)
or 
List.map() -> Iterator((index, value) => f)
Run Code Online (Sandbox Code Playgroud)

看来这是最简单的方法,但是似乎不存在此功能仍然很奇怪。

Iterable<int>.generate(list.length).forEach( (index) => {
  newList.add(list[index], index)
});
Run Code Online (Sandbox Code Playgroud)

编辑:

感谢@ hemanth-raj,我得以找到所需的解决方案。我将把它放在这里,供需要执行类似操作的任何人使用。

List<Widget> _buildWidgets(List<Object> list) {
    return list
        .asMap()
        .map((index, value) =>
            MapEntry(index, _buildWidget(index, value)))
        .values
        .toList();
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以创建一个同步生成器函数以返回一个可迭代

Iterable<MapEntry<int, T>> enumerate<T>(Iterable<T> items) sync* {
  int index = 0;
  for (T item in items) {
    yield MapEntry(index, item);
    index = index + 1;
  }
}

//and use it like this.
var list = enumerate([0,1,3]).map((entry) => Text("index: ${entry.key}, value: ${entry.value}"));
Run Code Online (Sandbox Code Playgroud)

Nea*_*arl 57

从 Dart 2.7 开始,您可以使用extension方法来扩展功能,Iterable而不必编写辅助函数:

extension ExtendedIterable<E> on Iterable<E> {
  /// Like Iterable<T>.map but callback have index as second argument
  Iterable<T> mapIndexed<T>(T Function(E e, int i) f) {
    var i = 0;
    return map((e) => f(e, i++));
  }

  void forEachIndexed(void Function(E e, int i) f) {
    var i = 0;
    forEach((e) => f(e, i++));
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

final inputs = ['a', 'b', 'c', 'd', 'e', 'f'];
final results = inputs
  .mapIndexed((e, i) => 'item: $e, index: $i')
  .toList()
  .join('\n');

print(results);

// item: a, index: 0
// item: b, index: 1
// item: c, index: 2
// item: d, index: 3
// item: e, index: 4
// item: f, index: 5
Run Code Online (Sandbox Code Playgroud)
inputs.forEachIndexed((e, i) => print('item: $e, index: $i'));

// item: a, index: 0
// item: b, index: 1
// item: c, index: 2
// item: d, index: 3
// item: e, index: 4
// item: f, index: 5
Run Code Online (Sandbox Code Playgroud)

现场演示

  • 这是最好的答案,这甚至适用于 Flutter 项目,您可以返回小部件而不仅仅是字符串。 (11认同)
  • 仍然感到失望的是,这不是内置在 dart 中的。 (2认同)

Hem*_*Raj 42

有一种asMap方法可以将列表转换为映射,其中键是索引,值是索引中的元素。请在这里看一下文档。

例:

List _sample = ['a','b','c'];
_sample.asMap().forEach((index, value) => f);
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!

  • 对于 JS 开发人员来说非常令人失望,这里需要“转换”来迭代带有索引的列表 (12认同)
  • map() 应该返回一个值,以便将一种类型的列表转换为新的列表类型。forEach() 返回 void。您不妨只使用 forEach()。 (5认同)
  • 我感觉这并不能保证订购。可以? (5认同)
  • @sleighty 它保证了排序。如 [`.asMap` 文档](https://api.dart.dev/stable/dart-core/List/asMap.html) 中所述: * `Map.keys` `Iterable` 迭代此索引按数字顺序列出。* (5认同)
  • “.asMap” 的一个缺点是它仅适用于“List”,而不适用于任意“Iterable”。 (3认同)

小智 14

首先使用asMap将 List 转换为 map。元素的索引是关键。元素成为价值。使用条目将键和值映射到您想要的任何内容。

List rawList = ["a", "b", "c"];
List<String> argList = rawList.asMap().entries.map((e) => '${e.key}:${e.value}').toList();
print(argList);
Run Code Online (Sandbox Code Playgroud)

输出:

[0:a, 1:b, 2:c]
Run Code Online (Sandbox Code Playgroud)


Tim*_*mmm 12

我最初认为['one', 'two', 'three'].asMap().forEach((index, value) { ... });会非常低效,因为它看起来像是将列表转换为地图。实际上它不是 - 文档说它创建了一个不可变的列表视图。我仔细检查了dart2js这段代码:

void main() {
  final foo = ['one', 'two', 'three'];
  foo.asMap().forEach((idx, val) {
    print('$idx: $val');
  });
}
Run Code Online (Sandbox Code Playgroud)

它会生成大量代码!但要点是这样的:

  main: function() {
    var foo = H.setRuntimeTypeInfo(["one", "two", "three"], ...);
    new H.ListMapView(foo, ...).forEach$1(0, new F.main_closure());
  },

  H.ListMapView.prototype = {
    forEach$1: function(_, f) {
      var t1, $length, t2, i;
      ...
      t1 = this._values;
      $length = t1.length;
      for (t2 = $length, i = 0; i < $length; ++i) {
        if (i >= t2)
          return H.ioore(t1, i);
        f.call$2(i, t1[i]);
        t2 = t1.length;
        if ($length !== t2)
          throw H.wrapException(P.ConcurrentModificationError$(t1));
      }
    },
    ...
  },

  F.main_closure.prototype = {
    call$2: function(idx, val) {
      ...
      H.printString("" + idx + ": " + H.S(val));
    },
    $signature: 1
  };
Run Code Online (Sandbox Code Playgroud)

所以它足够聪明,可以做有效率的事情!很聪明。

当然你也可以只使用普通的 for 循环:

for (var index = 0; index < values.length; ++index) {
  final value = values[index];
Run Code Online (Sandbox Code Playgroud)


Tar*_*ish 12

使用-> mapIndexed(index, Element) 函数

将每个元素及其索引映射到新值。

import 'package:collection/collection.dart';
Run Code Online (Sandbox Code Playgroud)

并使用地图索引如下

(List).mapIndexed<Widget>(
 (mapIndex, mapElement) => Positioned(
  left: mapIndex.toDouble() * 5,
  child: Card(
   color: Colors.blue,
    child: Image.network(
     '${mapElement.ImageURL}',
      height: 80,
      width: 80))))
Run Code Online (Sandbox Code Playgroud)

请参考: https ://pub.dev/documentation/collection/latest/collection/IterableExtension/mapIndexed.html


Viv*_*ien 10

没有内置函数来获取迭代索引。

如果像我一样,您不喜欢Map仅为简单索引构建(数据结构)的想法,则可能需要的是map为您提供索引的(函数)。让我们称之为mapIndexed(就像在Kotlin中一样):

children: mapIndexed(
  list,
  (index, item) => Text("event_$index")
).toList();
Run Code Online (Sandbox Code Playgroud)

的实现mapIndexed很简单:

Iterable<E> mapIndexed<E, T>(
    Iterable<T> items, E Function(int index, T item) f) sync* {
  var index = 0;

  for (final item in items) {
    yield f(index, item);
    index = index + 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @DavidRees thx的建议!我还重命名了函数`mapIndexed`。 (2认同)
  • @Timmmm我认为 `asMap()` 会花费额外的循环来检索数据,因此它不会像上面的 `mapIndexed()` 那样高效。 (2认同)

use*_*706 9

您可以使用集合mapIndexed包中的扩展:

import 'package:collection/collection.dart';

void main() {
  final nums = [1, 2, 3];
  final strs = nums.mapIndexed((index, element) => index.toString() + '_' + element.toString()).toList();

  print(strs); //  [0_1, 1_2, 2_3]
}
Run Code Online (Sandbox Code Playgroud)


use*_*494 6

为方便起见,您可以使用此扩展方法。

extension CollectionUtil<T> on Iterable<T>  {

  Iterable<E> mapIndexed<E, T>(E Function(int index, T item) transform) sync* {
    var index = 0;

    for (final item in this) {
      yield transform(index, item as T);
      index++;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*ies 5

Lukas Renggli的更多程序包包括许多有用的工具,包括“索引”功能,它可以完全满足您的需求。从文档:

indexed(['a', 'b'], offset: 1)
  .map((each) => '${each.index}: ${each.value}')
  .join(', ');
Run Code Online (Sandbox Code Playgroud)

(除非您具有Smalltalk背景,否则您可以忽略offset参数)。


Jør*_*sen 5

建立在@Hemanth Raj答案上。

要将其转换回您可以

List<String> _sample = ['a', 'b', 'c'];
_sample.asMap().values.toList(); 
//returns ['a', 'b', 'c'];
Run Code Online (Sandbox Code Playgroud)

或者,如果您需要映射函数的索引,则可以执行以下操作:

_sample
.asMap()
.map((index, str) => MapEntry(index, str + index.toString()))
.values
.toList();
// returns ['a0', 'b1', 'c2']
Run Code Online (Sandbox Code Playgroud)


nav*_*vid 5

您可以使用Iterable.generate工厂。以下代码将映射Iterable使用索引和值。

extension IterableMapIndex<T> on Iterable<T> {
  Iterable<E> mapIndexed<E>(E f(int index, T t)) {
    return Iterable.generate(this.length, (index)=>f(index, elementAt(index)));
  }
}
Run Code Online (Sandbox Code Playgroud)