我有下面的代码,在来C++,我需要翻译成C#。
int** _cartesianProduct(int sizeA, int sizeB) {
int** array = (int**)malloc(sizeof(int*) * sizeA * sizeB + sizeof(int) * 2 * sizeA * sizeB);
int* ptr = (int*)(array + sizeA * sizeB);
for (int i = 0; i < sizeA * sizeB; ++i)
array[i] = (ptr + 2 * i);
for (int i = 0; i < sizeA; ++i)
for (int k = 0; k < sizeB; ++k) {
array[i * sizeB + k][0] = i;
array[i * sizeB + k][1] = k;
}
return array;
}
这将为传递给它的所有可能的数字组合创建一个 "笛卡尔乘积 "数组。我在这里的具体困惑是这个块在做什么?
int* ptr = (int*)(array + sizeA * sizeB);
for (int i = 0; i < sizeA * sizeB; ++i)
array[i] = (ptr + 2 * i);
或者更具体地说,这一行 int* ptr = (int*)(array + sizeA * sizeB);
?
这就分配了一个内存块来存储一个二维数组,作为一个数组的数组。C语言中的数组是以指向更多数组的指针数组的形式存储的;我的第一反应是 "呸",但这里有一些优雅的地方,因为所有的东西都是作为一个单一的内存块返回的,可以在之后一次性的free()ed。
这段代码
如何将其移植到C#中?这取决于你想如何消耗生成的值。我可能会把它做成一个值元组的数组。
var array = Enumerable.Range(0, sizeA).SelectMany(a =>
Enumerable.Range(0, sizeB).Select(b => (a,b))).ToList();
或 .ToArray()
. 如果你确实想要锯齿状的数组版本,你可以用 new[] { a, b }
而不是在内部选择。
说点题外话。
这段代码可能看起来像一个 C++
代码,但我会这样称呼它。它更像是 C
伪装的代码 C++
的结果,因为 malloc
明确地投向 int**
(需要在 C++
在 C
陈旧的)。)
C++版本的可以是这样的。
std::vector<std::array<int, 2>> cartesianProduct(int sizeA, int sizeB) {
std::vector<std::array<int, 2>> result(sizeA * sizeB);
for (int i = 0; i < sizeA; ++i) {
for (int k = 0; k < sizeB; ++k) {
result[i * sizeB + k] = { i, k };
}
}
return result;
}