Dart 语言中的笛卡尔积

Yun*_*nus 5 cartesian dart

如何在 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 语言没有。

Roc*_*ice 10

使用 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]]);
    }
  }
}

Run Code Online (Sandbox Code Playgroud)

您可以根据需要输入任意长度的字符串数组。像这样使用:

  PermutationAlgorithmStrings algo = PermutationAlgorithmStrings([
                      ["A", "B", "C"],
                      ["W", "X", "Y", "Z"],
                      ["M", "N"]
                    ]);
Run Code Online (Sandbox Code Playgroud)

输出:

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]]
Run Code Online (Sandbox Code Playgroud)


lrn*_*lrn 6

您可以将其写为一个简单的列表:

var product = [for (var x in X) for (var y in Y) "$x$y"];
Run Code Online (Sandbox Code Playgroud)

(假设XY包含字符串,并且您想要的组合是串联,否则编写其他内容而不是"$x$y"组合xy值)。

对于任意数量的列表,它会变得更加复杂。我可能更喜欢惰性地生成组合,而不是在没有必要的情况下同时将所有列表保留在内存中。如果需要,您可以随时创建它们。

也许尝试这样的事情:

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);
}
Run Code Online (Sandbox Code Playgroud)