问题 如何从C#中的2D数组中获取完整的行或列


我不想使用锯齿状数组,我有一个2D数组,我希望得到一个完整的列或行而不通过它循环。有谁知道如何做到这一点。

double [,]  array = new double [3,3] ;

1   2   3 
4   5   6

Out: 1   2   3  or 2   5 

2532
2017-12-11 16:18


起源



答案:


您可以使用优化它来获取行 Buffer.BlockCopy(),但要获得一个列,你将不得不循环。 Buffer.BlockCopy() 最终使用处理器指令来复制内存块,所以它非常快。

将代码放入扩展方法以便于调用更方便。注意 Buffer.BlockCopy() 只能用于基本类型的数组,即 intdoublechar 等等。这不包括 string

这是一个可编辑的例子:

using System;
using System.Linq;
using System.Runtime.InteropServices;

namespace ConsoleApplication4
{
    public static class Program
    {
        private static void Main()
        {
            var array = new [,]
            {
                {0.1, 0.2, 0.3, 0.4, 0.5},
                {1.1, 1.2, 1.3, 1.4, 1.5},
                {2.1, 2.2, 2.3, 2.4, 2.5},
                {3.1, 3.2, 3.3, 3.4, 3.5},
            };

            var row = array.GetRow(2);

            // This prints 2.1, 2.2, 2.3, 2.4, 2.5

            Console.WriteLine(string.Join(", ", row.Select(element => element.ToString())));
        }
    }

    public static class ArrayExt
    {
        public static T[] GetRow<T>(this T[,] array, int row)
        {
            if (!typeof(T).IsPrimitive)
                throw new InvalidOperationException("Not supported for managed types.");

            if (array == null)
                throw new ArgumentNullException("array");

            int cols = array.GetUpperBound(1) + 1;
            T[] result = new T[cols];
            int size = Marshal.SizeOf<T>();

            Buffer.BlockCopy(array, row*cols*size, result, 0, cols*size);

            return result;
        }
   }
}

10
2017-12-12 09:18





要从多维数组中获取特定的行或列,可以使用一些LINQ:

public class CustomArray<T>
{
    public T[] GetColumn(T[,] matrix, int columnNumber)
    {
        return Enumerable.Range(0, matrix.GetLength(0))
                .Select(x => matrix[x, columnNumber])
                .ToArray();
    }

    public T[] GetRow(T[,] matrix, int rowNumber)
    {
        return Enumerable.Range(0, matrix.GetLength(1))
                .Select(x => matrix[rowNumber, x])
                .ToArray();
    }
}

3
2017-07-09 08:57





一个 替代 你可以这样做的方法是使用一个 列表而不是数组

特别是在你的情况下,你会做这样的事情:

  1. 最初创建一个表示数组元组的内部类
  2. 创建内部类的列表
  3. 填充内部类
  4. 获取包含特定内容的行
  5. 获取包含特定内容的列
public static void Main(string[] args)
{
    // #2 -- Instantiate List of myClass
    List<myClass> myList = new List<myClass>();
    //
    // #3 -- Populate the list
    myList.Add(new myClass(1,2,3));           
    myList.Add(new myClass(3,4,5));
    myList.Add(new myClass(5,6,6));
    //
    // #4 -- Get the line where a == 1
    myList.Find(x=>x.a == 1);
    //
    // #5 -- Get column b
    myList.Select(x=>x.b);
}
// #1 -- Create the inner class
public class myClass
{
    public int a;
    public int b;
    public int c;
    public myClass(int a, int b, int c)
    {
        this.a =a;
        this.b =b;
        this.c =c;
    }
}

0
2017-11-07 13:31



这不是一个锯齿状的阵列吗?不妨使用内置类型。选择方法是循环。 - David Burg


答案:


您可以使用优化它来获取行 Buffer.BlockCopy(),但要获得一个列,你将不得不循环。 Buffer.BlockCopy() 最终使用处理器指令来复制内存块,所以它非常快。

将代码放入扩展方法以便于调用更方便。注意 Buffer.BlockCopy() 只能用于基本类型的数组,即 intdoublechar 等等。这不包括 string

这是一个可编辑的例子:

using System;
using System.Linq;
using System.Runtime.InteropServices;

namespace ConsoleApplication4
{
    public static class Program
    {
        private static void Main()
        {
            var array = new [,]
            {
                {0.1, 0.2, 0.3, 0.4, 0.5},
                {1.1, 1.2, 1.3, 1.4, 1.5},
                {2.1, 2.2, 2.3, 2.4, 2.5},
                {3.1, 3.2, 3.3, 3.4, 3.5},
            };

            var row = array.GetRow(2);

            // This prints 2.1, 2.2, 2.3, 2.4, 2.5

            Console.WriteLine(string.Join(", ", row.Select(element => element.ToString())));
        }
    }

    public static class ArrayExt
    {
        public static T[] GetRow<T>(this T[,] array, int row)
        {
            if (!typeof(T).IsPrimitive)
                throw new InvalidOperationException("Not supported for managed types.");

            if (array == null)
                throw new ArgumentNullException("array");

            int cols = array.GetUpperBound(1) + 1;
            T[] result = new T[cols];
            int size = Marshal.SizeOf<T>();

            Buffer.BlockCopy(array, row*cols*size, result, 0, cols*size);

            return result;
        }
   }
}

10
2017-12-12 09:18





要从多维数组中获取特定的行或列,可以使用一些LINQ:

public class CustomArray<T>
{
    public T[] GetColumn(T[,] matrix, int columnNumber)
    {
        return Enumerable.Range(0, matrix.GetLength(0))
                .Select(x => matrix[x, columnNumber])
                .ToArray();
    }

    public T[] GetRow(T[,] matrix, int rowNumber)
    {
        return Enumerable.Range(0, matrix.GetLength(1))
                .Select(x => matrix[rowNumber, x])
                .ToArray();
    }
}

3
2017-07-09 08:57





一个 替代 你可以这样做的方法是使用一个 列表而不是数组

特别是在你的情况下,你会做这样的事情:

  1. 最初创建一个表示数组元组的内部类
  2. 创建内部类的列表
  3. 填充内部类
  4. 获取包含特定内容的行
  5. 获取包含特定内容的列
public static void Main(string[] args)
{
    // #2 -- Instantiate List of myClass
    List<myClass> myList = new List<myClass>();
    //
    // #3 -- Populate the list
    myList.Add(new myClass(1,2,3));           
    myList.Add(new myClass(3,4,5));
    myList.Add(new myClass(5,6,6));
    //
    // #4 -- Get the line where a == 1
    myList.Find(x=>x.a == 1);
    //
    // #5 -- Get column b
    myList.Select(x=>x.b);
}
// #1 -- Create the inner class
public class myClass
{
    public int a;
    public int b;
    public int c;
    public myClass(int a, int b, int c)
    {
        this.a =a;
        this.b =b;
        this.c =c;
    }
}

0
2017-11-07 13:31



这不是一个锯齿状的阵列吗?不妨使用内置类型。选择方法是循环。 - David Burg


我们需要的是一个jugged数组(不是一个多维数组)

https://msdn.microsoft.com/en-us/library/2s05feca.aspx

int[][] jaggedArray = new int[3][];
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[] { 0, 2, 4, 6 };
jaggedArray[2] = new int[] { 11, 22 };

列的完整示例:

using System;
using System.Collections.Generic;

namespace Rextester
{
    public class Program
    {

        public static T[] column<T>(T[][] jaggedArray,int wanted_column)
        {
            T[] columnArray = new T[jaggedArray.Length];
            T[] rowArray;
            for(int i=0;i<jaggedArray.Length;i++)
            {
                rowArray=jaggedArray[i];
                if(wanted_column<rowArray.Length)
                    columnArray[i]=rowArray[wanted_column];
            }
            return columnArray;
        }

        public static void Main(string[] args)
        {
            //Your code goes here
                int[][] jaggedArray = new int[3][];
                jaggedArray[0] = new int[5];
                jaggedArray[1] = new int[] { 0, 2, 4, 6 };
                jaggedArray[2] = new int[] { 11, 22 };

                Console.WriteLine("Hello, world!");
                Console.WriteLine(string.Join(" ",jaggedArray[1]));
                Console.WriteLine(string.Join(" ",column(jaggedArray,1)));
        }
    }
}

另一个相同的想法,使用扩展

using System;
using System.Collections.Generic;

namespace Rextester
{
    public static class MyExtensions
    {
        public static string Extend(this Array array)
        {
            return "Yes, you can extend an array";
        }

        public static T[] column<T>(this T[,] multidimArray,int wanted_column)
        {
            int l=multidimArray.GetLength(0);
            T[] columnArray = new T[l];
            for(int i=0;i<l;i++)
            {
              columnArray[i]=multidimArray[i,wanted_column];
            }
            return columnArray;
        }

        public static T[] row<T>(this T[,] multidimArray,int wanted_row)
        {
            int l=multidimArray.GetLength(1);
            T[] rowArray = new T[l];
            for(int i=0;i<l;i++)
            {
              rowArray[i]=multidimArray[wanted_row,i];
            }
            return rowArray;
        }


    } 

    public class Program
    {


        public static void Main(string[] args)
        {
                Console.WriteLine("Hello, world!");

                int [,] multidimArray = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
                Console.WriteLine(string.Join(" ",multidimArray.column(0)));
                Console.WriteLine(string.Join(" ",multidimArray.row(0)));

        }
    }
}

0
2018-02-18 22:56



这对于获取完整的列没有帮助,只是帮助处理行。 - David Burg
没有奇迹。正如Behrooz在这里说的那样......你可以为行填充两次,为列填充一次。或使用一些访问者Behrooz说,或使用访问器并将其复制到数组并返回数组的函数。 - Shimon Doodkin


如果您知道要输出的数字的索引..那么您不需要使用循环来获得所需的输出...

double[,] array = new double[3,3] {{1,2,3}, {4,5,6}, {7,8,9}}; 

int firstNum = array[0,1];
int secondNum = array[1,1];

这将获得2,5


-1
2017-12-11 16:53



问题的例子是用一个小数组简化的。问题的精神是为任意维度的数组执行此操作。列出将在循环中的每个命令都没有回答如何在没有循环的情况下实现目标的问题。 - David Burg