コンピュータや音楽の事書いてます

2次元配列をLINQ可能に

なるべく少ない手数でダメなソースを改善したいとき、急激にやる気を削がれるのが2次元配列だと思う。
コンストラクタで参照をコピーするので、メモリを2倍消費する事はないはず。(未検証)

使用時

var qArray = 
    new Queryable2DimensionalArray<string>(昔の人が作った不便な2次元配列);
//2カラム目が"B"の行だけ列挙する
var result = qArray.Select((row) => row[2] == "B");

class定義

/// <summary>
/// 2次元配列をジャグ配列の様な扱いにして、LINQを使って、片方の次元を1つずつ取り出せる様にする
/// </summary>
/// <remarks>
/// 通常、2次元配列でforeachなどを使うと1次元的にアクセスしてしまうが、
/// これだと、ジャグ配列の様な取り出し方が出来る。
/// 2次元配列はLINQ出来ないが、出来るようになる。
/// </remarks>
/// <typeparam name="T"></typeparam>
class Queryable2DimensionalArray<T> : IEnumerable<T[]>
{
    T[,] data;
    int dim0 = 0;
    int dim1 = 1;

    public Queryable2DimensionalArray(T[,] d)
    {
        data = d;
    }
    /// <summary>
    /// reverseがtrueの場合、0次元と1次元が入れ替わる
    /// </summary>
    /// <param name="d"></param>
    /// <param name="reverse"></param>
    public Queryable2DimensionalArray(T[,] d, bool reverse)
    {
        data = d;
        if (reverse) { dim0 = 1; dim1 = 0; }
    }

    public IEnumerator<T[]> GetEnumerator()
    {
        for (int i = 0; i < data.GetUpperBound(dim0) + 1; i++)
        {
            T[] result = new T[data.GetUpperBound(dim1) + 1];
            for (int j = 0; j < data.GetUpperBound(dim1) + 1; j++)
            {
                result[j] = dim0 == 0 ? data[i, j] : data[j, i];
            }
            yield return result;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

}

2015/11/05 ソース修正