Dart 语言中的笛卡尔积
Cartesian product in Dart Language
如何在 Dart 语言中创建动态列表数的笛卡尔积?
例如我有两个列表:
X: [A, B, C]; Y: [W, X, Y, Z]
我想创建这样的列表[AW, AX, AY, AZ, BW, BX, BY, BZ, CW, CX, CY, CZ]
虽然 Python、Java 有预实现的库,但我认为 Dart 语言有 none。
试试这个解决方案:
void main() {
List<String> a = ['A','B','C'];
List<String> b = ['X','Y','Z'];
List<String> c = a.map((ai) => b.map((bi) => ai+bi).toList()).expand((i) => i).toList();
c.forEach((ci) => print(ci));
}
你可以把它写成一个简单的列表:
var product = [for (var x in X) for (var y in Y) "$x$y"];
(假设 X
和 Y
包含字符串,并且您想要的组合是连接,否则写其他东西而不是 "$x$y"
来组合 x
和 y
值).
对于任意数量的列表,它会变得更加复杂。我可能更喜欢懒惰地生成组合,而不是在没有必要的情况下将所有列表同时保存在内存中。如果需要,您可以随时创建它们。
也许可以试试:
Iterable<List<T>> cartesian<T>(List<List<T>> inputs) sync* {
if (inputs.isEmpty) {
yield List<T>(0);
return;
}
var indices = List<int>.filled(inputs.length, 0);
int cursor = inputs.length - 1;
outer: do {
yield [for (int i = 0; i < indices.length; i++) inputs[i][indices[i]]];
do {
int next = indices[cursor] += 1;
if (next < inputs[cursor].length) {
cursor = inputs.length - 1;
break;
}
indices[cursor] = 0;
cursor--;
if (cursor < 0) break outer;
} while (true);
} while (true);
}
使用 Dart 2.5.0 测试:
class PermutationAlgorithmStrings {
final List<List<String>> elements;
PermutationAlgorithmStrings(this.elements);
List<List<String>> permutations() {
List<List<String>> perms = [];
generatePermutations(elements, perms, 0, []);
return perms;
}
void generatePermutations(List<List<String>> lists, List<List<String>> result, int depth, List<String> current) {
if (depth == lists.length) {
result.add(current);
return;
}
for (int i = 0; i < lists[depth].length; i++) {
generatePermutations(lists, result, depth + 1, [...current, lists[depth][i]]);
}
}
}
您可以输入任意长度的字符串数组。
像这样使用:
PermutationAlgorithmStrings algo = PermutationAlgorithmStrings([
["A", "B", "C"],
["W", "X", "Y", "Z"],
["M", "N"]
]);
输出:
output: [[A, W, M], [A, W, N], [A, X, M], [A, X, N], [A, Y, M], [A, Y, N], [A, Z, M], [A, Z, N], [B, W, M], [B, W, N], [B, X, M], [B, X, N], [B, Y, M], [B, Y, N], [B, Z, M], [B, Z, N], [C, W, M], [C, W, N], [C, X, M], [C, X, N], [C, Y, M], [C, Y, N], [C, Z, M], [C, Z, N]]
函数式求解。
//declare type matters!
List<List<dynamic>> cards = [
[1, 2, 3],
[4, 5],
['x','y']
];
笛卡尔积
//or List flatten(List iterable) => iterable.expand((e) => e is List ? flatten(e) : [e]).toList(); // toList() cannot omit
Iterable flatten(Iterable iterable) => iterable.expand((e) => e is Iterable ? flatten(e) : [e]);
//cannot omit paramenter type
List<List<dynamic>> cartesian(List<List<dynamic>> xs) =>
xs.reduce((List<dynamic> acc_x, List<dynamic> x) => // type cannot be omit
acc_x.expand((i) => x.map((j) => flatten([i, j]).toList())).toList());
也许使用 Dart 动态类型是愚蠢的,你可以使用类型友好的版本
I quit using reduce function because of its strict dimension limiting on parameters as well as returning values
类型友好
List<List<T>> cartesian<T>(List<List<T>> list) {
var head = list[0];
var tail = list.skip(1).toList();
List<List<T>> remainder = tail.length > 0 ? cartesian([...tail]) : [[]];
List<List<T>> rt = [];
for (var h in head) {
for (var r in remainder)
rt.add([h, ...r]);
}
return rt;
}
如何在 Dart 语言中创建动态列表数的笛卡尔积?
例如我有两个列表:
X: [A, B, C]; Y: [W, X, Y, Z]
我想创建这样的列表[AW, AX, AY, AZ, BW, BX, BY, BZ, CW, CX, CY, CZ]
虽然 Python、Java 有预实现的库,但我认为 Dart 语言有 none。
试试这个解决方案:
void main() {
List<String> a = ['A','B','C'];
List<String> b = ['X','Y','Z'];
List<String> c = a.map((ai) => b.map((bi) => ai+bi).toList()).expand((i) => i).toList();
c.forEach((ci) => print(ci));
}
你可以把它写成一个简单的列表:
var product = [for (var x in X) for (var y in Y) "$x$y"];
(假设 X
和 Y
包含字符串,并且您想要的组合是连接,否则写其他东西而不是 "$x$y"
来组合 x
和 y
值).
对于任意数量的列表,它会变得更加复杂。我可能更喜欢懒惰地生成组合,而不是在没有必要的情况下将所有列表同时保存在内存中。如果需要,您可以随时创建它们。
也许可以试试:
Iterable<List<T>> cartesian<T>(List<List<T>> inputs) sync* {
if (inputs.isEmpty) {
yield List<T>(0);
return;
}
var indices = List<int>.filled(inputs.length, 0);
int cursor = inputs.length - 1;
outer: do {
yield [for (int i = 0; i < indices.length; i++) inputs[i][indices[i]]];
do {
int next = indices[cursor] += 1;
if (next < inputs[cursor].length) {
cursor = inputs.length - 1;
break;
}
indices[cursor] = 0;
cursor--;
if (cursor < 0) break outer;
} while (true);
} while (true);
}
使用 Dart 2.5.0 测试:
class PermutationAlgorithmStrings {
final List<List<String>> elements;
PermutationAlgorithmStrings(this.elements);
List<List<String>> permutations() {
List<List<String>> perms = [];
generatePermutations(elements, perms, 0, []);
return perms;
}
void generatePermutations(List<List<String>> lists, List<List<String>> result, int depth, List<String> current) {
if (depth == lists.length) {
result.add(current);
return;
}
for (int i = 0; i < lists[depth].length; i++) {
generatePermutations(lists, result, depth + 1, [...current, lists[depth][i]]);
}
}
}
您可以输入任意长度的字符串数组。 像这样使用:
PermutationAlgorithmStrings algo = PermutationAlgorithmStrings([
["A", "B", "C"],
["W", "X", "Y", "Z"],
["M", "N"]
]);
输出:
output: [[A, W, M], [A, W, N], [A, X, M], [A, X, N], [A, Y, M], [A, Y, N], [A, Z, M], [A, Z, N], [B, W, M], [B, W, N], [B, X, M], [B, X, N], [B, Y, M], [B, Y, N], [B, Z, M], [B, Z, N], [C, W, M], [C, W, N], [C, X, M], [C, X, N], [C, Y, M], [C, Y, N], [C, Z, M], [C, Z, N]]
函数式求解。
//declare type matters!
List<List<dynamic>> cards = [
[1, 2, 3],
[4, 5],
['x','y']
];
笛卡尔积
//or List flatten(List iterable) => iterable.expand((e) => e is List ? flatten(e) : [e]).toList(); // toList() cannot omit
Iterable flatten(Iterable iterable) => iterable.expand((e) => e is Iterable ? flatten(e) : [e]);
//cannot omit paramenter type
List<List<dynamic>> cartesian(List<List<dynamic>> xs) =>
xs.reduce((List<dynamic> acc_x, List<dynamic> x) => // type cannot be omit
acc_x.expand((i) => x.map((j) => flatten([i, j]).toList())).toList());
也许使用 Dart 动态类型是愚蠢的,你可以使用类型友好的版本
I quit using reduce function because of its strict dimension limiting on parameters as well as returning values
类型友好
List<List<T>> cartesian<T>(List<List<T>> list) {
var head = list[0];
var tail = list.skip(1).toList();
List<List<T>> remainder = tail.length > 0 ? cartesian([...tail]) : [[]];
List<List<T>> rt = [];
for (var h in head) {
for (var r in remainder)
rt.add([h, ...r]);
}
return rt;
}