在 Dart 中的迭代器上创建 sum、min、max 属性
Creating sum, min, max properties on iterators in Dart
我有以下内容,适用于 int
s:
extension IterableInt on Iterable<int> {
int get max => reduce(math.max);
int get min => reduce(math.min);
int get sum => reduce((a, b) => a + b);
}
我想让它更通用以包括小数并创建了这个:
extension IterableNum on Iterable<num> {
num get max => reduce(math.max);
num get min => reduce(math.min);
num get sum => reduce((a, b) => a + b);
}
这些大多失败,使用以下测试:
void main(List<String> args) {
print([1.2, 1.3, 5, 2.2].sum); //works
print([1.2, 1.3, 5, 2.2].max); //works
print([1.2, 1.3, 5, 2.2].min); //works
print([1.2, 1.3, 5.0, 2.2].sum); //does not work
print([1, 2, 3].max); //does not work
print([1, 2, 3].min); //does not work
print([1, 2, 3].sum); //does not work
}
decimal
案例返回的错误是:
type '(num, num) => num' is not a subtype of type '(double, double) => double' of 'combine'
int
类似,在消息中指的是int
而不是double
。
模式似乎是,如果列表中混合有 int
s 和 decimal
s 则没问题。如果全部为 int
或全部为 decimal
,则失败。
我已经使用 fold
重新定义了属性(并添加了 multiply
),这有效:
extension IterableNum on Iterable<num> {
num get max => fold(first, math.max);
num get min => fold(first, math.min);
num get sum => fold(0, (a, b) => a + b);
num get multiply => fold(1, (a, b) => a * b);
}
谁能解释一下为什么 IterableNum
(使用 reduce
)的第一个版本不起作用?
问题是 reduce
对其参数函数非常挑剔。
A List<int>
的 reduce
需要 int Function(int, int)
类型的函数。别无他法。如果你将这个 List<int>
转换为 List<num>
,你得到的东西看起来像是期望得到一个 num Function(num, num)
,但实际上需要一个 int Function(int, int)
。很难同时满足这两个条件(你需要 int Function(num, num)
,而 (a, b) => a + b
不是。
(这都是因为 Dart class 泛型是 不安全的 协变。List<int>
总是被认为是 List<num>
的子类型,即使某些函数在 List<num>
).
实际上不可用
使用fold
是一个很好的解决办法。它允许您指定不同于元素类型的 return 类型。它还要求您以该类型的值开头,这就是为什么不总是可以使用 fold
而不是 reduce
.
的原因
它不起作用,因为您创建了更高级别的列表(num
类型的子类)。
您的(扩展)代码应该更通用(更通用)。
喜欢这个代码:extension IterableNum<T extends num> on Iterable<T>
.
void main(List<String> args) {
print([1.2, 1.3, 5, 2.2].runtimeType);
print([1.2, 1.3, 5.0, 2.2].runtimeType);
}
结果:
List<num>
List<double>
更正代码如下:
import 'dart:math' as math;
void main(List<String> args) {
print([1.2, 1.3, 5, 2.2].runtimeType);
print([1.2, 1.3, 5.0, 2.2].runtimeType);
print([1.2, 1.3, 5, 2.2].sum); //works
print([1.2, 1.3, 5, 2.2].max); //works
print([1.2, 1.3, 5, 2.2].min); //works
print([1.2, 1.3, 5.0, 2.2].sum); // WORKS!!!
print([1, 2, 3].max); // WORKS!!!
print([1, 2, 3].min); // WORKS!!!
print([1, 2, 3].sum); // WORKS!!!
}
extension IterableNum<T extends num> on Iterable<T> {
T get max => reduce(math.max);
T get min => reduce(math.min);
T get sum => reduce((a, b) => a + b as T);
}
结果:
List<num>
List<double>
9.7
5
1.2
9.7
3
1
6
我有以下内容,适用于 int
s:
extension IterableInt on Iterable<int> {
int get max => reduce(math.max);
int get min => reduce(math.min);
int get sum => reduce((a, b) => a + b);
}
我想让它更通用以包括小数并创建了这个:
extension IterableNum on Iterable<num> {
num get max => reduce(math.max);
num get min => reduce(math.min);
num get sum => reduce((a, b) => a + b);
}
这些大多失败,使用以下测试:
void main(List<String> args) {
print([1.2, 1.3, 5, 2.2].sum); //works
print([1.2, 1.3, 5, 2.2].max); //works
print([1.2, 1.3, 5, 2.2].min); //works
print([1.2, 1.3, 5.0, 2.2].sum); //does not work
print([1, 2, 3].max); //does not work
print([1, 2, 3].min); //does not work
print([1, 2, 3].sum); //does not work
}
decimal
案例返回的错误是:
type '(num, num) => num' is not a subtype of type '(double, double) => double' of 'combine'
int
类似,在消息中指的是int
而不是double
。
模式似乎是,如果列表中混合有 int
s 和 decimal
s 则没问题。如果全部为 int
或全部为 decimal
,则失败。
我已经使用 fold
重新定义了属性(并添加了 multiply
),这有效:
extension IterableNum on Iterable<num> {
num get max => fold(first, math.max);
num get min => fold(first, math.min);
num get sum => fold(0, (a, b) => a + b);
num get multiply => fold(1, (a, b) => a * b);
}
谁能解释一下为什么 IterableNum
(使用 reduce
)的第一个版本不起作用?
问题是 reduce
对其参数函数非常挑剔。
A List<int>
的 reduce
需要 int Function(int, int)
类型的函数。别无他法。如果你将这个 List<int>
转换为 List<num>
,你得到的东西看起来像是期望得到一个 num Function(num, num)
,但实际上需要一个 int Function(int, int)
。很难同时满足这两个条件(你需要 int Function(num, num)
,而 (a, b) => a + b
不是。
(这都是因为 Dart class 泛型是 不安全的 协变。List<int>
总是被认为是 List<num>
的子类型,即使某些函数在 List<num>
).
使用fold
是一个很好的解决办法。它允许您指定不同于元素类型的 return 类型。它还要求您以该类型的值开头,这就是为什么不总是可以使用 fold
而不是 reduce
.
它不起作用,因为您创建了更高级别的列表(num
类型的子类)。
您的(扩展)代码应该更通用(更通用)。
喜欢这个代码:extension IterableNum<T extends num> on Iterable<T>
.
void main(List<String> args) {
print([1.2, 1.3, 5, 2.2].runtimeType);
print([1.2, 1.3, 5.0, 2.2].runtimeType);
}
结果:
List<num>
List<double>
更正代码如下:
import 'dart:math' as math;
void main(List<String> args) {
print([1.2, 1.3, 5, 2.2].runtimeType);
print([1.2, 1.3, 5.0, 2.2].runtimeType);
print([1.2, 1.3, 5, 2.2].sum); //works
print([1.2, 1.3, 5, 2.2].max); //works
print([1.2, 1.3, 5, 2.2].min); //works
print([1.2, 1.3, 5.0, 2.2].sum); // WORKS!!!
print([1, 2, 3].max); // WORKS!!!
print([1, 2, 3].min); // WORKS!!!
print([1, 2, 3].sum); // WORKS!!!
}
extension IterableNum<T extends num> on Iterable<T> {
T get max => reduce(math.max);
T get min => reduce(math.min);
T get sum => reduce((a, b) => a + b as T);
}
结果:
List<num>
List<double>
9.7
5
1.2
9.7
3
1
6