| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of utilslib; | 5 part of utilslib; |
| 6 | 6 |
| 7 typedef num NumericValueSelector<T>(T value); | 7 typedef num NumericValueSelector<T>(T value); |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * General purpose collection utilities. | 10 * General purpose collection utilities. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 // TODO(jmesserly): we won't need to do this once List | 33 // TODO(jmesserly): we won't need to do this once List |
| 34 // implements insertAt | 34 // implements insertAt |
| 35 if (arr is ObservableList) { | 35 if (arr is ObservableList) { |
| 36 // TODO(jmesserly): shouldn't need to cast after testing instanceof | 36 // TODO(jmesserly): shouldn't need to cast after testing instanceof |
| 37 ObservableList obs = arr; | 37 ObservableList obs = arr; |
| 38 obs.recordListInsert(pos, value); | 38 obs.recordListInsert(pos, value); |
| 39 } | 39 } |
| 40 } | 40 } |
| 41 } | 41 } |
| 42 | 42 |
| 43 // Collection<T> supports most of the ES 5 list methods, but it's missing | |
| 44 // map. | |
| 45 | |
| 46 // TODO(jmesserly): we might want a version of this that return an iterable, | |
| 47 // however JS, Python and Ruby versions are all eager. | |
| 48 static List map(Iterable source, var mapper) { | |
| 49 // TODO(jmesserly): I was trying to set the capacity here, but instead it | |
| 50 // seems to create a fixed list. Hence assigning by index below. | |
| 51 List result = new List(source is List ? (source as List).length : null); | |
| 52 int i = 0; | |
| 53 for (final item in source) { | |
| 54 result[i++] = mapper(item); | |
| 55 } | |
| 56 return result; | |
| 57 } | |
| 58 | |
| 59 /** | 43 /** |
| 60 * Finds the item in [source] that matches [test]. Returns null if | 44 * Finds the item in [source] that matches [test]. Returns null if |
| 61 * no item matches. The typing should be: | 45 * no item matches. The typing should be: |
| 62 * T find(Iterable<T> source, bool test(T item)), but we don't have generic | 46 * T find(Iterable<T> source, bool test(T item)), but we don't have generic |
| 63 * functions. | 47 * functions. |
| 64 */ | 48 */ |
| 65 static find(Iterable source, bool test(item)) { | 49 static find(Iterable source, bool test(item)) { |
| 66 for (final item in source) { | 50 for (final item in source) { |
| 67 if (test(item)) return item; | 51 if (test(item)) return item; |
| 68 } | 52 } |
| 69 | 53 |
| 70 return null; | 54 return null; |
| 71 } | 55 } |
| 72 | 56 |
| 73 /** Compute the minimum of an iterable. Returns null if empty. */ | 57 /** Compute the minimum of an iterable. Returns null if empty. */ |
| 74 static num min(Iterable source) { | 58 static num min(Iterable source) { |
| 75 final iter = source.iterator(); | 59 final iter = source.iterator; |
| 76 if (!iter.hasNext) { | 60 if (!iter.moveNext()) { |
| 77 return null; | 61 return null; |
| 78 } | 62 } |
| 79 num best = iter.next(); | 63 num best = iter.current; |
| 80 while (iter.hasNext) { | 64 while (iter.moveNext()) { |
| 81 best = Math.min(best, iter.next()); | 65 best = Math.min(best, iter.current); |
| 82 } | 66 } |
| 83 return best; | 67 return best; |
| 84 } | 68 } |
| 85 | 69 |
| 86 /** Compute the maximum of an iterable. Returns null if empty. */ | 70 /** Compute the maximum of an iterable. Returns null if empty. */ |
| 87 static num max(Iterable source) { | 71 static num max(Iterable source) { |
| 88 final iter = source.iterator(); | 72 final iter = source.iterator; |
| 89 if (!iter.hasNext) { | 73 if (!iter.moveNext()) { |
| 90 return null; | 74 return null; |
| 91 } | 75 } |
| 92 num best = iter.next(); | 76 num best = iter.current; |
| 93 while (iter.hasNext) { | 77 while (iter.moveNext()) { |
| 94 best = Math.max(best, iter.next()); | 78 best = Math.max(best, iter.current); |
| 95 } | 79 } |
| 96 return best; | 80 return best; |
| 97 } | 81 } |
| 98 | 82 |
| 99 /** Orders an iterable by its values, or by a key selector. */ | 83 /** Orders an iterable by its values, or by a key selector. */ |
| 100 static List orderBy(Iterable source, [NumericValueSelector selector = null]) { | 84 static List orderBy(Iterable source, [NumericValueSelector selector = null]) { |
| 101 final result = new List.from(source); | 85 final result = new List.from(source); |
| 102 sortBy(result, selector); | 86 sortBy(result, selector); |
| 103 return result; | 87 return result; |
| 104 } | 88 } |
| 105 | 89 |
| 106 /** Sorts a list by its values, or by a key selector. */ | 90 /** Sorts a list by its values, or by a key selector. */ |
| 107 // TODO(jmesserly): we probably don't want to call the key selector more than | 91 // TODO(jmesserly): we probably don't want to call the key selector more than |
| 108 // once for a given element. This would improve performance and the API | 92 // once for a given element. This would improve performance and the API |
| 109 // contract could be stronger. | 93 // contract could be stronger. |
| 110 static void sortBy(List list, [NumericValueSelector selector = null]) { | 94 static void sortBy(List list, [NumericValueSelector selector = null]) { |
| 111 if (selector != null) { | 95 if (selector != null) { |
| 112 list.sort((x, y) => selector(x) - selector(y)); | 96 list.sort((x, y) => selector(x) - selector(y)); |
| 113 } else { | 97 } else { |
| 114 list.sort((x, y) => x - y); | 98 list.sort((x, y) => x - y); |
| 115 } | 99 } |
| 116 } | 100 } |
| 117 | 101 |
| 118 /** Compute the sum of an iterable. An empty iterable is an error. */ | 102 /** Compute the sum of an iterable. An empty iterable is an error. */ |
| 119 static num sum(Iterable source, [NumericValueSelector selector = null]) { | 103 static num sum(Iterable source, [NumericValueSelector selector = null]) { |
| 120 final iter = source.iterator(); | 104 final iter = source.iterator; |
| 105 bool wasEmpty = true; |
| 121 num total = 0; | 106 num total = 0; |
| 122 if (selector != null) { | 107 if (selector != null) { |
| 123 do { | 108 for (var element in source) { |
| 124 total += selector(iter.next()); | 109 wasEmpty = false; |
| 125 } while (iter.hasNext); | 110 total += selector(element); |
| 111 } |
| 126 } else { | 112 } else { |
| 127 do { | 113 for (num element in source) { |
| 128 total += iter.next(); | 114 wasEmpty = false; |
| 129 } while (iter.hasNext); | 115 total += element; |
| 116 } |
| 130 } | 117 } |
| 118 if (wasEmpty) throw new StateError("No elements"); |
| 131 return total; | 119 return total; |
| 132 } | 120 } |
| 133 | 121 |
| 134 // TODO(jmesserly): something like should exist on Map, either a method or a | 122 // TODO(jmesserly): something like should exist on Map, either a method or a |
| 135 // constructor, see bug #5340679 | 123 // constructor, see bug #5340679 |
| 136 static void copyMap(Map dest, Map source) { | 124 static void copyMap(Map dest, Map source) { |
| 137 for (final k in source.keys) { | 125 for (final k in source.keys) { |
| 138 dest[k] = source[k]; | 126 dest[k] = source[k]; |
| 139 } | 127 } |
| 140 } | 128 } |
| 141 } | 129 } |
| OLD | NEW |