将int[][]转换为int**的最佳方法
本文关键字:int 最佳 方法 转换 | 更新日期: 2023-09-27 18:02:08
这是一个令人好奇的问题。我确实有一个现有的解决方案,但我想知道人们是否知道更好的方法。
我的来电者想用int[][]给我打电话。我有一个例程需要处理一个int**。进行转换的最佳方法是什么?换句话说:
public static void Func1(int[][] data) {
Func2(data); //how to do this?
}
private unsafe static void Func2(int** data) {
//process data
}
以下是我能想到的最好的方法。它工作得很好,但我不能说我对递归方法(以及它所需的O(data.Length(堆栈空间( 100%满意
public static void Main() {
var test=new[] {
new [] {10},
new [] {20,30},
new [] {40,50,60},
new [] {70,80,90,100},
};
MySolution_Func1(test);
}
public unsafe static void MySolution_Func1(int[][] data) {
var items=new int*[data.Length];
Recurse(0, data, items);
}
public unsafe static void Recurse(int index, int[][] data, int*[] build) {
if(index==data.Length) {
fixed(int** finalp=build) {
Func2(finalp);
}
} else {
fixed(int* nextp=data[index]) {
build[index]=nextp;
Recurse(index+1, data, build);
}
}
}
private unsafe static void Func2(int** data) {
for(var j=0; j<4; ++j) {
for(var i=0; i<j+1; ++i) {
Debug.WriteLine("{0},{1}: {2}", j, i, data[j][i]);
}
}
}
不需要复制整个数组。您可以创建一个指针数组(即IntPtr[]
(,然后将其强制转换为int**
。这不好看,我也不建议这么做。但这是可以做到的。下面的代码显示了如何操作。
int[][] myArray = new int[10][];
for (int i = 0; i < 10; ++i)
{
int[] x = new int[10];
for (int j = 0; j < 10; ++j)
{
x[j] = 10 * i + j;
}
myArray[i] = x;
}
// Output the array
Console.WriteLine("int[][]");
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", myArray[i][j]);
}
Console.WriteLine();
}
// Convert to int*[]
unsafe
{
GCHandle[] handles = new GCHandle[10];
IntPtr[] ArrayOfPointer = new IntPtr[10];
for (int i = 0; i < 10; ++i)
{
handles[i] = GCHandle.Alloc(myArray[i], GCHandleType.Pinned);
ArrayOfPointer[i] = handles[i].AddrOfPinnedObject();
}
// Okay, let's output that
Console.WriteLine("int*[]");
for (int i = 0; i < 10; ++i)
{
int* p = (int*)ArrayOfPointer[i];
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", *p);
++p;
}
Console.WriteLine();
}
// now convert to int**
GCHandle bigHandle = GCHandle.Alloc(ArrayOfPointer, GCHandleType.Pinned);
int** ppInt = (int**)bigHandle.AddrOfPinnedObject();
// and output it
Console.WriteLine("int**");
int** pa = ppInt;
for (int i = 0; i < 10; ++i)
{
int* p = *pa;
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", *p);
++p;
}
Console.WriteLine();
++pa;
}
// Need to free the handles
bigHandle.Free();
for (int i = 0; i < 10; ++i)
{
handles[i].Free();
}
}
public unsafe void ConvertToNative(int[][] jarray, out int** ptr)
{
ptr= (int**)Marshal.AllocHGlobal(jarray.Length*sizeof(int));
for (int i = 0; i < jarray.Length; i++)
{
*(ptr+i) = (int*)Marshal.AllocHGlobal(jarray[i].Length*sizeof(int));
for (int j = 0; j < jarray[i].Length; j++)
{
(*(i + ptr))[j] = jarray[i][j];
}
}
}
这是有效的,但使用了非托管内存,并且没有递归,这有效吗?
如果您愿意将所有数据复制到另一个缓冲区:,您可以使用O(1(堆栈空间
public unsafe static void AlternateSolution_Func1(int[][] data) {
var buffer=new int[data.Sum(a => a.Length)];
fixed(int* pBuffer=buffer) {
var items=new int*[data.Length];
int count=0;
for(int i=0; i<data.Length; ++i) {
items[i]=pBuffer+count;
var array=data[i];
for(int j=0; j<array.Length; ++j) {
pBuffer[count++]=array[j];
}
}
fixed(int** pItems=items) {
Func2(pItems);
}
}
}