Di dart ada yang setara dengan yang umum:
enumerate(List) -> Iterator((index, value) => f)
or
List.enumerate() -> Iterator((index, value) => f)
or
List.map() -> Iterator((index, value) => f)
Tampaknya ini adalah cara termudah tetapi masih terlihat aneh bahwa fungsi ini tidak akan ada.
Iterable<int>.generate(list.length).forEach( (index) => {
newList.add(list[index], index)
});
Edit:
Terima kasih kepada @ hemanth-raj saya dapat menemukan solusi yang saya cari. Saya akan meletakkan ini di sini untuk siapa saja yang perlu melakukan hal serupa.
List<Widget> _buildWidgets(List<Object> list) {
return list
.asMap()
.map((index, value) =>
MapEntry(index, _buildWidget(index, value)))
.values
.toList();
}
Alternatively you could create a synchronous generator function to return a iterable
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}"));
Map#forEach
? is it what you want?List
? what do you mean? the docs say: "Applies f to each key/value pair of the map. Calling f must not add or remove keys from the map."Jawaban:
There is a
asMap
method which converts the list to a map where the keys are the index and values are the element at index. Please take a look at the docs here.Example:
List _sample = ['a','b','c']; _sample.asMap().forEach((index, value) => f);
Hope this helps!
sumber
There is no built-in function to get the iteration index.
If like me you don't like the idea to build a
Map
(the data structure) just for a simple index, what you probably want is amap
(the function) which gives you the index. Let's call itmapIndexed
(like in Kotlin):children: mapIndexed( list, (index, item) => Text("event_$index") ).toList();
The implementation of
mapIndexed
is simple: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; } }
sumber
mapIndexed
.asMap().forEach()
is essentially the same as this - see my answer.asMap()
will cost additional loop to retrieve data, thus it will not efficient asmapIndexed()
above.Building on @Hemanth Raj answer.
To convert it back you could do
List<String> _sample = ['a', 'b', 'c']; _sample.asMap().values.toList(); //returns ['a', 'b', 'c'];
Or if you needed the index for a mapping function you could do this:
_sample .asMap() .map((index, str) => MapEntry(index, str + index.toString())) .values .toList(); // returns ['a0', 'b1', 'c2']
sumber
Starting with Dart 2.7, you can use
extension
to extend the functionalities ofIterable
instead of having to write helper methodsextension ExtendedIterable<E> on Iterable<E> { /// Like Iterable<T>.map but callback have index as second argument Iterable<T> mapIndex<T>(T f(E e, int i)) { var i = 0; return this.map((e) => f(e, i++)); } void forEachIndex(void f(E e, int i)) { var i = 0; this.forEach((e) => f(e, i++)); } }
Usage:
final inputs = ['a', 'b', 'c', 'd', 'e', 'f']; final results = inputs .mapIndex((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.forEachIndex((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
sumber
Lukas Renggli's more package includes many useful tools including 'indexed' which does exactly what you want. From the docs:
indexed(['a', 'b'], offset: 1) .map((each) => '${each.index}: ${each.value}') .join(', ');
(You can ignore the offset argument unless you have a Smalltalk background :-).
sumber
I initially thought
['one', 'two', 'three'].asMap().forEach((index, value) { ... });
would be really inefficient because it looks like it is converting the list to a map. Actually it isn't - the documentation says it creates an immutable view of the list. I double checked with thedart2js
of this code:void main() { final foo = ['one', 'two', 'three']; foo.asMap().forEach((idx, val) { print('$idx: $val'); }); }
It generates lot of code! But the gist is this:
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 };
So it is smart enough to do the efficient thing! Pretty clever.
Of course you can also just use a normal for loop:
for (var index = 0; index < values.length; ++index) { final value = values[index];
sumber
For convenience you can use this extension method.
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++; } } }
sumber
Use asMap to convert List to map first. The index of element is the key. The element becomes value. Use entries to map the key and value to anything you want.
List rawList = ["a", "b", "c"]; List<String> argList = rawList.asMap().entries.map((e) => '${e.key}:${e.value}').toList(); print(argList);
Output:
[0:a, 1:b, 2:c]
sumber