web-dev-qa-db-ja.com

C#で2D配列から完全な行または列を取得する方法

ギザギザの配列を使用したくないし、2D配列があり、ループせずに完全な列または行を取得したい。誰もがそれをどのように行うことができるか考えていますか。

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

1   2   3 
4   5   6

Out: 1   2   3  or 2   5 
23
User1551892

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;

            if (typeof(T) == typeof(bool))
                size = 1;
            else if (typeof(T) == typeof(char))
                size = 2;
            else
                size = Marshal.SizeOf<T>();

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

            return result;
        }
   }
}
11
Matthew Watson

多次元配列から特定の行または列を取得するには、いくつかの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();
    }
}
22
Alex Podles

ここに私がそれをやった方法があります

GetLength(0)

列を取得して使用するには

GetLength(1)

2次元配列の行を取得し、他の誰かがこれを必要とする場合はforループでループします。

string text = "";
for (int i = 0; i < array.GetLength(0); i++)
   {
      text += Convert.ToString(array[i, 2]) + "\n";
   }
1
E.Lahu

alternativeを行う方法は、配列の代わりにリストを使用することです。

具体的には、次のようなことをします。

  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
Pontios

必要なのはジャグ配列です(多次元配列ではありません)

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
Shimon Doodkin