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

将int[][]转换为int**的最佳方法

不需要复制整个数组。您可以创建一个指针数组(即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);
    }
  }
}