【问题标题】:How to Convert int[] to int[,] - C#如何将 int[] 转换为 int[,] - C#
【发布时间】:2013-04-18 15:59:39
【问题描述】:

我有一维的 int 数组:

var intArray=new[] { 1, 2, 3, 4, 5, 6 };

我想把它转换成二维,比如:

var intArray2D=new[,] { {1, 2}, {3, 4}, {5, 6} };

如何使用 C# 实现这一点?

【问题讨论】:

  • {1,2,3,4,5,6,8,9,10,11,12} 有什么用? {{1,2,3,4},{5,6,7,8},{9,10,11,12}{{1,2,3},{4,5,6},{7,8,9},{10,11,12}}
  • 你总是有一个偶数的长度吗?元组总是成对的吗?查看dotnetperls.com/tuple,看看这是否有助于您更好地定义您的问题。
  • 对于单列数组到双列数组的假设,正如他/她的问题中所述。
  • 我的意思是 {1,2,3,4,5,6}{{1,2}, {3,4}, {5,6}} int[] 是 x,y 坐标。数组的第一个元素是 x 坐标;第二个元素是y坐标;等等。我希望它以易于理解的形式将其分配给 Point[]。

标签: c# arrays multidimensional-array matrix


【解决方案1】:

也许有一个循环:

for (int i = 0; i < oldArr.Length; i=i+2)
{
    newArr[i/2, 0] = oldArr[i];
    newArr[i/2, 1] = oldArr[i + 1];
}

未经测试,但应该让你指向正确的方向......

【讨论】:

  • 只有数组中的第一项([0,1])被赋值,其他数组的值都是0。
【解决方案2】:

如果一维数组包含row major order中的原始数据,并且二维数组的总容量等于一维数组的长度,则可以使用这个。

int[] source = new int[6];
int[,] target = new int[3, 2];
Buffer.BlockCopy(source, 0, target, 0, source.Length * sizeof(int));

请注意,与 Array.Copy 和其他数组/列表方法不同,Buffer.BlockCopy 对许多 字节 数据进行操作,即使数组的每个元素都大于 1 个字节。它也只对原始数据类型的数组进行操作。

其他参考资料:

编辑:这是一个完整的单元测试。

[TestMethod]
public void SOTest16203210()
{
    int[] source = new int[6] { 1, 2, 3, 4, 5, 6 };
    int[,] destination = new int[3, 2];
    Buffer.BlockCopy(source, 0, destination, 0, source.Length * sizeof(int));
    Assert.AreEqual(destination[0, 0], 1);
    Assert.AreEqual(destination[0, 1], 2);
    Assert.AreEqual(destination[1, 0], 3);
    Assert.AreEqual(destination[1, 1], 4);
    Assert.AreEqual(destination[2, 0], 5);
    Assert.AreEqual(destination[2, 1], 6);
}

【讨论】:

    【解决方案3】:

    我相信您想将一个整数数组拆分为一个每个包含两个整数的数组:

    int[] list = new int[] { 1, 2, 3, 4, 5, 6};
    int[][] newlist = new int[list.Length / 2][];
    for (int i = 0, n = 0; i < list.Length; i += 2, n++)
    {
        newlist[n] = new[] { list[i], list[i + 1] };
    }
    

    要将其分配给Points,您可以尝试:

    List<Point> plist = new List<Point>();
    for (int i = 0; i < list.Length; i += 2)
    {
        plist.Add(new Point(list[i], list[i + 1]));
    }
    

    【讨论】:

    • 使用数组数组 ([][]),当第二维是常数时,与一个连续矩阵 ([,]) 相比效率低。
    • 您正在使用对数组的引用数组而不是大数组。为此编写您自己的测试或打开一本书。
    • 由于 List 解决方案,我将此标记为答案。我要求 int[,] 使我的问题更直接,并使用与 Point[] 相同的技术。 List 只是让事情变得更容易。谢谢。
    • 刚刚完成我的测试。与您的信念相反或出于其他原因,您的建议较慢。第一个代码在第一次运行时平均在 6.5 毫秒内完成,而带有int[,] 的版本平均在 8 毫秒内完成。我可以将我的代码发布在某处供您查看和图片,但我希望您自己测试并确认这一点。谢谢。 ps:在VS2010(.Net Framework 4)上使用性能向导测试。
    • 如果您有时间,我们可以继续聊天。正如我所说,我认为不会有任何切实的表现。当然,对于非常大的数组,结果可能会有所不同,但这绝对不适用于我上面演示的这种情况。
    【解决方案4】:

    您可以使用此代码。在这里你可以发送任何你喜欢的长度。您可以将 arry[] “deivde” 为 arry[,] 任何 lenth.2 或 3 或任何你喜欢的!只要 size % a.length ==0 !!!!

    代码

            static int[,] convert(int[] a, int size)
        {
            int[,] value = new int[a.Length / size, size];
            int counter = 0;
            //
            for (int b = 0; b < value.GetLength(0); b++)
                for (int c = 0; c < value.GetLength(1); c++)
                {
                     value[b, c] = a[counter];
                      counter++;
               }
            return value;
        }
    

    【讨论】:

      【解决方案5】:

      如果维度的乘积相同,最快的方法可能是使用固定语句固定矩阵,然后使用编组类将连续块从数组复制到从 void* 创建的 IntPtr你是从固定的。

      您必须将其包装在 unsafe 语句中,并在程序集的构建配置中启用 unsafe。

      【讨论】:

      • 这与问题有什么关系?
      【解决方案6】:

      我已将它从 vb 转换为 c#

      int Size = OldArray.Length;
      int[,] NewPoints = null;
      
      if (Size % 2 != 0) {
        //Error - Array has odd number of elements!
      } else {
        for (i = 0; i <= Size - 1; i += 2) {
          Array.Resize(ref AllPoints, (i / 2) + 1, 2);
          NewPoints[i / 2, 0] = OldArray(i);
          NewPoints[i / 2, 1] = OldArray(i + 1);
        }
      }
      

      【讨论】:

        【解决方案7】:

        你可以试试这个:

        int [] a = {1,2,3,4,5,6};
        int [,] b = new int[a.Length/2,2];
        
        for(int i = 0;i<a.Length;i++)
        {
            b[i/2,i%2] = a[i];
        }
        

        请注意,i/2 是整数除法,因此 4/2 和 5/2 都会给出 2,这是原始数组中元组 5 和 6 在 2Darray 中的正确索引。第二个索引由reminder除以2确定,如果索引是偶数则为0,如果原始数组中的项目的索引为奇数则为1。

        【讨论】:

          【解决方案8】:

          我会考虑这个数组的任何维度:

          public class TestClass {
              public static void TestMethod2D() {
                  var intLinear=new[] { 1, 2, 3, 4, 5, 6 };
                  var indexer2D=new ArrayIndexer<int>(3, 2);
          
                  for(var i=intLinear.Length; i-->0; indexer2D[i]=intLinear[i])
                      ;
          
                  var int2D=(int[,])indexer2D.ToArray();
              }
          
              public static void TestMethod4D() {
                  var intLinear=new[] { 1, 2, 3, 4, 5, 6 };
                  var indexer4D=new ArrayIndexer<int>(2, 2, 2, 2);
          
                  for(var i=intLinear.Length; i-->0; indexer4D[i]=intLinear[i])
                      ;
          
                  var int4D=(int[, , ,])indexer4D.ToArray();
              }
          }
          
          public partial class ArrayIndexer<T> {
              public Array ToArray() {
                  return m_Array;
              }
          
              public ArrayIndexer(params int[] lengths) {
                  m_Array=Array.CreateInstance(typeof(T), lengths);
              }
          
              public T this[params int[] indices] {
                  set {
                      m_Array.SetValue(value, indices.Transform(m_Array));
                  }
          
                  get {
                      return (T)m_Array.GetValue(indices.Transform(m_Array));
                  }
              }
          
              Array m_Array;
          }
          
          public static partial class ArrayExtensions {
              public static int[] Transform(
                  this int[] indices, Array array, bool isRowMajor=true) {
                  if(indices.Length>array.Rank)
                      return indices;
                  else {
                      var list=indices.ToList();
          
                      if(isRowMajor)
                          list.Reverse();
          
                      for(int r, q=0, i=0, count=array.Rank; count-->0; ++i) {
                          var index=isRowMajor?count-i:i;
          
                          if(indices.Length>i) {
                              q=Math.DivRem(indices[i]+q, array.GetLength(index), out r);
                              list[i]=r;
                          }
                          else {
                              if(index<0) {
                                  list.Add(q);
                                  q=0;
                              }
                              else {
                                  q=Math.DivRem(q, array.GetLength(index), out r);
                                  list.Add(r);
                              }
                          }
                      }
          
                      if(isRowMajor)
                          list.Reverse();
          
                      return list.ToArray();
                  }
              }
          }
          

          ArrayExtensions.Transform 是一个索引转换器,它对给定数组的几何形状执行线性转换。 isRowMajor 控制布局,例如您将在x, yy, x 顺序中视为int[,]

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-25
          • 2013-01-24
          • 2011-12-21
          • 1970-01-01
          相关资源
          最近更新 更多