-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Map should have a getter for its key/value pairs #7088
Comments
Removed Type-Defect label. |
From discussion https://groups.google.com/a/dartlang.org/forum/?fromgroups#!topic/misc/Y0TfPuQD4uU Original request: Sometimes when I have a map, I'd like to iterate over it which I can do with the forEach() method, but if I want to stop the iteration at some point, returning false won't work and neither can I break it. I can break with a for-in loop, but it does not support multiple values: for (String key, List<int> value in someMap) { I know that I could do something like: for (var key in someMap.keys) { However, it makes me think why can't we have a for-in with multiple values or why can't we return false in a callback for forEach()? There's also no StopIteration to throw. Is there a reason or is it something that "just isn't there"? |
This comment was originally written by @seaneagan The "pairs" getter also makes sense for List, see: https://code.google.com/p/dart/issues/detail?id=1322#c8 In JavaScript, the higher order Array method callbacks receive both the index and value, and this could provide similar functionality to Dart. Another example: void printEvens(List list) { printEvens(['a', 'b', 'c', 'd']); |
This comment was originally written by @seaneagan Now that we have List.asMap, we can probably settle for: list.asMap().pairs instead of: list.pairs |
Issue #12766 has been merged into this issue. |
1 similar comment
Issue #12766 has been merged into this issue. |
This comment was originally written by @seaneagan Tuples could be a good way to represent Map pairs. I guess the best bug for tuples is issue #10310. As seen here: tuples could be Iterables which also provide strongly typed fields for each index. So pairs could initially just return Iterables of length 2: Iterable<Iterable> get pairs; and then if we manage to get tuples which extend Iterable in the future, then these APIs can be updated to use those backwards compatibly. |
This comment was originally written by @Andersmholmgren I agree building on some tuple solution would be the nicest |
This comment was originally written by @Andersmholmgren Actually maybe the cleanest solution is if map directly implements Iterable<Tup2<A,B>> Assuming a language level syntax for tuples then you could do things like final m = {'foo':'1', 'bar':'2'}; Note (at least as a first step) you could do this today without first adding support for tuples except map couldn't actually declare that it implements Iterable. That would already provide most of the value. |
This comment was originally written by @seaneagan Any comment from the dart team on this one? Most other mainstream languages support this: JavaScript (ES 6): http://people.mozilla.org/~jorendorff/es6-draft.html#sec-map.prototype.entries There is obviously an overhead to creating the pair objects when iterating, but it is negligible for many use cases, and the use cases where it does matter can simply not use this API. I understand the hesitance to have Map implement Iterable<Pair> directly, but a "composition over inheritance" approach (e.g. a "pairs" or "entries" getter) seems pretty reasonable. |
Issue #16117 has been merged into this issue. |
Issue #21491 has been merged into this issue. |
Issue #16117 has been merged into this issue. |
This comment was originally written by jirkada...@gmail.com Angular.dart implemented KeyValue class dart-archive/angular.dart#394 Map.forEach() does not really work if I need to import 'dart:async'; Future doWork(v) { main() async { // With List, all works fine var l = [1,2,3,4,5,6]; // I can either use "smart" for loop, Future.forEach(l, (v) async { var m = {"I":1, "you":2, "he/she/it":3, "we": 4}; m.forEach((k,v) async { // and there is no Future.forEach for Maps |
This comment was originally written by greg...@gmail.com Would it be possible to just iterate on they key and look up the value? For example: Future doWork(key, value) => new Future.delayed(new Duration(seconds: 1)); main() { |
This comment was originally written by jirkad...@gmail.com @greg Sure. I came up with something similar Future forEach(Map map, Function f) { main() { Dart is Turing complete. Every problem can be "solved". |
This comment was originally written by greg.low...@gmail.com My point is that Future.forEach() works fine for maps. Future.forEach(m.keys, (key) => doWork(key, m[key])); Future.forEach(m.pairs, (pair) => doWork(pair.key, pair.value)); Future.forEachMap(m, doWork); These options all work, and are all pretty short. But if you'd like to advocate for adding a Future.forEachMap() function, then consider opening a bug for this rather than commenting against the bug for Map.pairs. Also worth considering, if using async/await, then Future.forEach() is not actually required at all: In the example from #16, the await statement in the closure passed to Future.forEach() can be omitted, as Future.forEach() already waits if the closure returns a Future. |
This comment was originally written by @seaneagan Milestone-2.0 ? |
This comment was originally written by @paulevans Is the reason that these closure implementations are being discussed over pairs / tuples because the allocations are actually harder on the vm then the setup for the forEach closures? Or is it a previous language bias? I'll put my hat in the ring and say I do miss the ability to iterate over pairs like I did in C#. Though looking over the implementation of one of the maps, say https://github.com/dart-lang/bleeding_edge/blob/3c02a5f133ca8d687fe21fd4beec0081745a376d/dart/runtime/lib/linked_hash_map.dart ... you may as well just iterate over the keys and ask for the values because that is exactly what this implementation is doing anyway. To involve Futures and the extra work + overhead they do compared to just moving over a collection seems like convenience triumphing over sanity. |
Maps now have an |
This issue was originally filed by @seaneagan
Map should have something like:
/// a live view of the [:Pair:]s contained in this Map
Set<Pair<K, V>> get pairs;
...and a corresponding constructor:
Map.fromPairs(Iterable<Pair<K, V>> pairs);
where Pair is just:
class Pair<K, V> {
const Pair(this.key, this.value);
final K key;
final V value;
}
Examples:
print(map.pairs.mappedBy((pair) => "${pair.key} -> ${pair.value}").join(", "));
var nonNullMap = new Map.fromPairs(map.pairs.where((pair) => pair.value != null));
The text was updated successfully, but these errors were encountered: