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

在省道中有任何相当于普通的东西:

enumerate(List) -> Iterator((index, value) => f)
or
List.enumerate()  -> Iterator((index, value) => f)
or
List.map() -> Iterator((index, value) => f)

这似乎是最简单的方法,但似乎仍然奇怪,这种功能不会存在。

Iterable<int>.generate(list.length).forEach( (index) => {
newList.add(list[index], index)
});
172474 次浏览

有一个 asMap方法,它将列表转换为一个映射,其中键为索引,值为索引处的元素。请看一下 给你号文件。

例如:

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

希望这个能帮上忙!

Lukas Renggli 的 更多软件包包括许多有用的工具,包括“索引”,它可以完全满足你的需求:

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

(您可以忽略偏移量参数,除非您具有 Smalltalk 背景: ——)。

基于@Hemanth Raj 的回答。

你可以把它转换回来

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

或者,如果需要映射函数的索引,可以这样做:

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

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

如果你像我一样不喜欢仅仅为了一个简单的索引构建一个 Map(数据结构) ,你可能想要的是一个 map(函数) ,它给你索引。让我们称之为 ABc2(就像在 Kotlin 一样) :

children: mapIndexed(
list,
(index, item) => Text("event_$index")
).toList();

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;
}
}

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

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

它生成 很多代码! 但要点是这样的:

  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
};

因此,它足够聪明,做有效的事情! 相当聪明。

当然,您也可以只使用一个普通的 for 循环:

for (var index = 0; index < values.length; ++index) {
final value = values[index];

可以使用 collection包中的 mapIndexedforEachIndexed扩展方法。注意,与 javascript 的 array.map()或 C # 的 IEnumerable.Select()不同,索引是回调的第一个参数,而不是第二个参数:

import 'package:collection/collection.dart';


void main() {
final inputs = ['a', 'b', 'c', 'd', 'e', 'f'];
final indexes = inputs.mapIndexed((index, element) => index).toList();
  

inputs.forEachIndexed((index, element) {
print('index: $index, element: $element');
});


print(indexes);
}

现场演示


旧答案

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

extension ExtendedIterable<E> on Iterable<E> {
/// Like Iterable<T>.map but the callback has 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++));
}
}

用法:

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
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

现场演示

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

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++;
}
}
}

首先使用 地图将 List 转换为 map。元素的索引是关键。元素变成了价值。使用 参赛作品将键和值映射到所需的任何内容。

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

产出:

[0:a, 1:b, 2:c]

您可以使用 Iterable.generate工厂。

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)));
}
}

使用省道 收集包裹可以访问各种列表扩展名

一个是 mapIndexed:

Iterable<R> mapIndexed<R>(R Function(int, E) convert)

所有可迭代扩展的列表

您可以使用 收藏品软件包中的 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]
}

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

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

import 'package:collection/collection.dart';

并使用如下地图索引

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

请参阅: Https://pub.dev/documentation/collection/latest/collection/iterableextension/mapindexed.html

package:quiver 包含一个类似于 Python 的 enumerate函数的 enumerate函数。

(请注意,虽然 package:quiver不是来自 Dart 团队,但它是由谷歌拥有和维护的,而且它的许多贡献者是谷歌的 Dart 和 Flutter 团队的成员。)

您可以创建另一个变量来获取 index。

    int index = 0;


array?.forEach((element) {
    

// your code is here


index++; // you should add this at end of the for loop
});