将2D阵列的2D阵列转换为单个2D阵列

时间:2021-12-02 01:22:19

So I have an object called, for lack of a better word, MatricesMatrix which is a Matrix of Matrices (everything is stored as a double[,]). I want to strip all of the values from the inner matrices into one big Matrix. Here is what I have so far:

所以我有一个对象,因为缺少一个更好的单词,MatricesMatrix是一个矩阵矩阵(一切都存储为double [,])。我想从内部矩阵中删除所有值到一个大矩阵。这是我到目前为止:

public Matrix ConvertToMatrix()
    {
        //Figure out how big the return matrix should be
        int totalRows = this.TotalRows();
        int totalColumns = this.TotalColumns();

        Matrix returnMatrix = new Matrix(totalRows, totalColumns);

        List<object> rowElementsList = new List<object>();

        //"outer" index means an index of the MatricesMatrix
        //"inner" index means an index of a Matrix within the Matrices Matrix

        //outer row loop
        for (int outerRowIndex = 0; outerRowIndex < NumberOfRows; outerRowIndex++)
        {
            //outer column loop
            for (int outerColumnIndex = 0; outerColumnIndex < NumberOfColumns; outerColumnIndex++)
            {
                Matrix currentMatrix = GetElement(outerRowIndex, outerColumnIndex);
                object element = null;

                //inner row loop
                for (int innerRowIndex = 0; innerRowIndex < currentMatrix.NumberOfRows; innerRowIndex++)
                {
                    //inner column loop
                    for (int innerColumnIndex = 0; innerColumnIndex < currentMatrix.NumberOfColumns; innerColumnIndex++)
                    {
                       element = currentMatrix.GetElement(innerRowIndex, innerColumnIndex);                          
                    }            
                }

                returnMatrix.SetElement(outerRowIndex, outerColumnIndex, (double)element);      





            }
        }

        return returnMatrix;
    }

Note that I have determined programmatically the total number of rows and columns the returnMatrix needs to have.

请注意,我已经以编程方式确定了returnMatrix需要具有的行和列的总数。

Here are some more guidelines and output cases:

以下是一些指南和输出案例:

  • Each element of the big matrix should be in the same position relative to the other elements of the big matrix that came from the Matrix inside of MatricesMatrix that the element came from.
  • 大矩阵的每个元素应该与大矩阵的其他元素处于相同的位置,该矩阵来自MatricesMatrix中的元素来自矩阵。
  • Each "matrix" (no longer in matrix form) inside of the big matrix should be in the same position relative to the other matrices inside of the big matrix as it was inside of the MatricesMatrix (with no overlapping, and 0's in any spaces left empty).
  • 大矩阵内部的每个“矩阵”(不再是矩阵形式)应该与大矩阵内部的其他矩阵处于相同的位置,因为它在MatricesMatrix内部(没有重叠,并且在任何空格中都是0)空)。

CASE 1

情况1

Given this input: a MatricesMatrix(2,2) with [0,0] = (2x2 matrix), [0,1] = (2x3 matrix), [1,0] = (2x2 matrix), and [1,1] = (2x3 matrix). That is,

给定此输入:MatricesMatrix(2,2),[0,0] =(2x2矩阵),[0,1] =(2x3矩阵),[1,0] =(2x2矩阵),[1,1] ] =(2x3矩阵)。那是,

将2D阵列的2D阵列转换为单个2D阵列

Output must be:

输出必须是:

将2D阵列的2D阵列转换为单个2D阵列

CASE 2

案例2

Given this input: a MatricesMatrix(2,2) with [0,0] = (1x1 matrix), [0,1] = (3x3 matrix), [1,0] = (2x2 matrix), and [1,1] = (4x4 matrix). That is,

给定此输入:MatricesMatrix(2,2),[0,0] =(1x1矩阵),[0,1] =(3x3矩阵),[1,0] =(2x2矩阵),[1,1] ] =(4x4矩阵)。那是,

将2D阵列的2D阵列转换为单个2D阵列

Output should be something like:

输出应该是这样的:

将2D阵列的2D阵列转换为单个2D阵列

Any assistance would be greatly appreciated!

任何帮助将不胜感激!

UPDATE: Here is a unit test for Case 1 that should pass:

更新:这是一个应该通过的案例1的单元测试:

    [TestMethod]
    public void MatricesMatrix_ConvertToMatrixTest()
    {
        Matrix m1 = new Matrix(2);
        Matrix m2 = new Matrix(2, 3);
        Matrix m3 = new Matrix(2);
        Matrix m4 = new Matrix(2, 3);

        double[] m1Row1 = { 1, 1 };
        double[] m1Row2 = { 1, 1 };

        double[] m2Row1 = { 2, 2, 2 };
        double[] m2Row2 = { 2, 2, 2 };            

        double[] m3Row1 = { 3, 3 };
        double[] m3Row2 = { 3, 3 };

        double[] m4Row1 = { 4, 4, 4 };
        double[] m4Row2 = { 4, 4, 4 };

        m1.SetRowOfMatrix(0, m1Row1);
        m1.SetRowOfMatrix(1, m1Row2);
        m2.SetRowOfMatrix(0, m2Row1);
        m2.SetRowOfMatrix(1, m2Row2); 
        m3.SetRowOfMatrix(0, m3Row1);
        m3.SetRowOfMatrix(1, m3Row2);
        m4.SetRowOfMatrix(0, m4Row1);
        m4.SetRowOfMatrix(1, m4Row2);

        MatricesMatrix testMatricesMatrix = new MatricesMatrix(2, 2);

        testMatricesMatrix.SetElement(0, 0, m1);
        testMatricesMatrix.SetElement(0, 1, m2);
        testMatricesMatrix.SetElement(1, 0, m3);
        testMatricesMatrix.SetElement(1, 1, m4);

        Matrix expectedResult = new Matrix(4, 5);

        double[] expectedRow1 = { 1, 1, 2, 2, 2 };
        double[] expectedRow2 = { 1, 1, 2, 2, 2 };
        double[] expectedRow3 = { 3, 3, 4, 4, 4 };
        double[] expectedRow4 = { 3, 3, 4, 4, 4 };

        expectedResult.SetRowOfMatrix(0, expectedRow1);
        expectedResult.SetRowOfMatrix(1, expectedRow2);
        expectedResult.SetRowOfMatrix(2, expectedRow3);
        expectedResult.SetRowOfMatrix(3, expectedRow4);

        Matrix actualResult = testMatricesMatrix.ConvertToMatrix();

        (actualResult == expectedResult).Should().BeTrue();

    }

3 个解决方案

#1


4  

I started with a simple Matrix class to hold the double[,]s. Nothing too fancy, just a simple array-of-arrays with a row and column count and array accessor.

我开始使用一个简单的Matrix类来保存double [,] s。没有什么太花哨的,只是一个简单的数组数组,带有行数和列数以及数组访问器。

class Matrix<T>
{
    public int Rows { get; private set; }
    public int Cols { get; private set; }

    private T[,] mat;

    public Matrix(int rowCount, int colCount)
    {
        Rows = rowCount;
        Cols = colCount;
        mat = new T[Rows, Cols];
    }

    public T this[int r, int c]
    {
        get { return mat[r, c]; }
        set { mat[r, c] = value; }
    }
}

Your second case looks more difficult (and like a better test of correctness) than the first, so I set up a metamatrix to match that.

你的第二种情况比第一种情况看起来更难(并且更像是对正确性的更好测试),所以我设置了一个与之匹配的元矩阵。

public static Matrix<double[,]> BuildMetaMatrix()
{
    Matrix<double[,]> m = new Matrix<double[,]>(2, 2);

    m[0, 0] = new double[,]
    {
        { 1 }
    };

    m[0, 1] = new double[,]
    {
        { 3, 3, 3 },
        { 3, 3, 3 },
        { 3, 3, 3 }
    };

    m[1, 0] = new double[,]
    {
        { 2, 2 },
        { 2, 2 }
    };

    m[1, 1] = new double[,]
    {
        {4, 4, 4, 4},
        {4, 4, 4, 4},
        {4, 4, 4, 4},
        {4, 4, 4, 4}
    };

    return m;
}

For convenience, I made a Place function that puts one matrix into another one at the given location.

为方便起见,我创建了一个Place函数,它将一个矩阵放在给定位置的另一个矩阵中。

static void Place(double[,] src, double[,] dest, int destR, int destC)
{
    for (int row = 0; row < src.GetLength(ROW_DIM); row++)
    {
        for (int col = 0; col < src.GetLength(COL_DIM); col++)
        {
            dest[row + destR, col + destC] = src[row, col];
        }
    }
}

The magic numbers fed into GetLength() were just asking for mistakes, so I defined some constants for them (ROW_DIM = 0 and COL_DIM = 1). I decided to handle the padding by figuring out how wide a column is and how tall a row is and skipping any extra elements after Place()ing the sub-matrix in. A GetRowHeight() and GetColWidth() method figure out the values.

输入GetLength()的神奇数字只是要求错误,所以我为它们定义了一些常量(ROW_DIM = 0和COL_DIM = 1)。我决定通过计算列的宽度和行的高度来处理填充,并在Place()子矩阵之后跳过任何额外的元素.GetRowHeight()和GetColWidth()方法计算出值。

public static int GetRowHeight(Matrix<double[,]> m, int row)
{
    int maxSeen = 0;

    for (int col = 0; col < m.Cols; col++)
    {
        if (m[row, col].GetLength(ROW_DIM) > maxSeen)
        {
            maxSeen = m[row, col].GetLength(ROW_DIM);
        }
    }

    return maxSeen;
}

public static int GetColWidth(Matrix<double[,]> m, int col)
{
    int maxSeen = 0;

    for (int row = 0; row < m.Rows; row++)
    {
        if (m[row, col].GetLength(COL_DIM) > maxSeen)
        {
            maxSeen = m[row, col].GetLength(COL_DIM);
        }
    }

    return maxSeen;
}

A Flatten() function loops through all the sub-matrices, Place()ing them at the appropriate row and column in a new matrix. It updates the next row and column after each Place() using the GetRowHeight() and GetColWidth() functions.

Flatten()函数循环遍历所有子矩阵,将它们放置在新矩阵中的适当行和列上。它使用GetRowHeight()和GetColWidth()函数更新每个Place()之后的下一行和列。

Matrix<double> Flatten(Matrix<Matrix<double>> src)
{
    // (7, 6) == (this.TotalRows(), this.TotalColumns())
    // from your code.
    Matrix<double> dest = new Matrix<double>(7, 6);

    int nextRow = 0;
    int nextCol = 0;

    for (int row = 0; row < src.Rows; row++)
    {
        for (int col = 0; col < src.Rows; col++)
        {
            dest.Place(src[row, col], nextRow, nextCol);
            nextCol += GetColWidth(src, col);
        }
        nextRow += GetRowHeight(src, row);
        nextCol = 0;
    }

    return dest;
}

A little glue to test it out...

一点胶水来测试它...

static void Main(string[] args)
{
    Matrix<double[,]> src = BuildMetaMatrix();
    double[,] dest = Flatten(src);

    Print(dest);
    Console.ReadLine();
}

static void Print(double[,] matrix)
{
    for (int row = 0; row < matrix.GetLength(ROW_DIM); row++)
    {
        for (int col = 0; col < matrix.GetLength(COL_DIM); col++)
        {
            Console.Write(matrix[row, col] + "\t");
        }
        Console.Write("\n");
    }
}

...and you get an output just like your second case with all the oddly fitting matrices and 0s in the empty places.*

......你得到的输出就像你的第二个案例一样,所有奇怪的拟合矩阵和空位的0。*

1       0       3       3       3       0
0       0       3       3       3       0
0       0       3       3       3       0
2       2       4       4       4       4
2       2       4       4       4       4
0       0       4       4       4       4
0       0       4       4       4       4

*The destination matrix gets its values initialized to default(double), which happens to be 0 (the value you wanted). If you need something other than default(double) for the empty places, you can probably get them by iterating over the new matrix and writing the new default value everywhere before Flatten()ing the metamatrix.

*目标矩阵将其值初始化为默认值(double),恰好为0(您想要的值)。如果您需要除默认值(双精度数)以外的空位置,则可以通过迭代新矩阵并在Flatten()处理元矩阵之前的任何位置写入新的默认值来获取它们。

(Thanks to Jeff Mercado for pointing out that multidimensional arrays' GetLength() method can be used to find their dimensions.)

(感谢Jeff Mercado指出可以使用多维数组的GetLength()方法来查找它们的尺寸。)

#2


1  

I think it would be beneficial to you to break up the solution into the quadrants you are trying to fill. This will all be under the assumption that we will only be combining 4 matrices in this 2x2 configuration. The same strategies explined here can be applied to other dimensions of matrices to be combined.

我认为将解决方案分解为您想要填充的象限会对您有所帮助。这一切都假设我们将只在这个2x2配置中组合4个矩阵。这里所示的相同策略可以应用于要组合的矩阵的其他维度。

So given 4 matrices A, B, C and D, we will try to build a resulting matrix in this arrangement:

因此,给定4个矩阵A,B,C和D,我们将尝试在这种安排中构建一个结果矩阵:

+---+---+
| A | B |
+---+---+
| C | D |
+---+---+

Before we can start, we will need to figure out the dimensions of the final result. This should hopefully make sense. We'll have a top half, bottom half, left half and right half.

在我们开始之前,我们需要弄清楚最终结果的维度。这应该是有道理的。我们将有一个上半部分,下半部分,左半部分和右半部分。

rows_top    = max(rows_A, rows_B)
rows_bottom = max(rows_C, rows_D)
rows_result = rows_top + rows_bottom

cols_left   = max(cols_A, cols_C)
cols_right  = max(cols_B, cols_D)
cols_result = cols_left + cols_right

Then we will want to consider which regions of the result matrix we want to copy each of the 4 matrices. Considering the origin at the top-left, everything on the right half will be shifted over by the size of the left half, everything on the bottom half will be shifted over by the size of the top half. The offsets for each of the matrices would be:

然后我们将要考虑结果矩阵的哪些区域要复制4个矩阵中的每一个。考虑到左上角的原点,右半部分的一切都会被左半部分的大小移动,下半部分的一切都会被上半部分的大小移动。每个矩阵的偏移量将是:

offset_A = (0, 0)
offset_B = (0, cols_left)
offset_C = (rows_top, 0)
offset_D = (rows_top, cols_left)

Now with all this information, we can start building up the result matrix. Just copy over the values from each matrix to the result, with the offsets applied.

现在有了所有这些信息,我们就可以开始构建结果矩阵了。只需将每个矩阵的值复制到结果中,并应用偏移量。

So in code, I would do this:

所以在代码中,我会这样做:

// I'm just going to use plain 2D arrays here
public T[,] Combine<T>(T[,] a, T[,] b, T[,] c, T[,] d)
{
    // get the total rows
    var rows_top    = Math.Max(a.GetLength(0), b.GetLength(0));
    var rows_bottom = Math.Max(c.GetLength(0), d.GetLength(0));
    var rows_result = rows_top + rows_bottom;

    // get the total columns
    var cols_left   = Math.Max(a.GetLength(1), c.GetLength(1));
    var cols_right  = Math.Max(b.GetLength(1), d.GetLength(1));
    var cols_result = cols_left + cols_right;

    // get the offsets
    var offset_a = Tuple.Create(0, 0);
    var offset_b = Tuple.Create(0, cols_left);
    var offset_c = Tuple.Create(rows_top, 0);
    var offset_d = Tuple.Create(rows_top, cols_left);

    // fill 'er up
    var result = new T[rows_result, cols_result];
    Fill(result, a, offset_a);
    Fill(result, b, offset_b);
    Fill(result, c, offset_c);
    Fill(result, d, offset_d);
    return result;
}

public void Fill<T>(T[,] result, T[,] source, Tuple<int, int> offset)
{
    for (var i = 0; i < source.GetLength(0); i++)
        for (var j = 0; j < source.GetLength(1); j++)
            result[offset.Item1 + i, offset.Item2 + j] = source[i, j];
}

Then to demonstrate the result in terms of case 2:

然后根据案例2展示结果:

const string A = "A", B = "B", C = "C", D = "D";
var a = new string[1,1]
{
    { A },
};
var b = new string[3, 3]
{
    { B, B, B },
    { B, B, B },
    { B, B, B },
};
var c = new string[2, 2]
{
    { C, C },
    { C, C },
};
var d = new string[4, 4]
{
    { D, D, D, D },
    { D, D, D, D },
    { D, D, D, D },
    { D, D, D, D },
};
var result = Combine(a, b, c, d);

This of course can be generalized to any size matrix of matrices. The concept is the same in every step of the process.

这当然可以推广到任何大小的矩阵矩阵。这个概念在这个过程的每一步都是一样的。

Given m x n matrices, we will try to build a resulting matrix in this arrangement:

给定m×n矩阵,我们将尝试在这种安排中构建一个结果矩阵:

+-----+-----+-----+
| 0,0 | ... | 0,n |
+-----+-----+-----+
| ... |     | ... |
+-----+-----+-----+
| m,0 | ... | m,n |
+-----+-----+-----+
  1. Get the dimensions of each of the slices.

    获取每个切片的尺寸。

    rows_0 = max(rows_0_0, ..., rows_0_n)
    ...
    rows_m = max(rows_m_0, ..., rows_m_n)
    rows_result = sum(rows_0, ..., rows_m)
    
    cols_0 = max(cols_0_0, ..., cols_m_0)
    ...
    cols_n = max(cols_0_n, ..., cols_m_n)
    cols_result = sum(cols_0, ..., cols_m)
    
  2. Get the offsets for each of the matrices. Each vertical slice is offset to the left by the total amount of columns in the previous vertical slices. Each horizontal slice is offset to the down by the total amount of rows in the previous horizontal slices.

    获取每个矩阵的偏移量。每个垂直切片向左偏移前一垂直切片中的总列数。每个水平切片向下偏移前一水平切片中的总行数。

    offset_0_0 = (0, 0)
    ...
    offset_m_n = (sum(rows_0, ..., rows_m-1), sum(cols_0, ..., cols_n-1))
    

So now we can build up the result matrix.

所以现在我们可以建立结果矩阵。

public T[,] Combine<T>(T[,][,] m)
{
    // get the rows
    var rows = GetSliceRows(m);
    var rows_result = rows.Sum();

    // get the cols
    var cols = GetSliceCols(m);
    var cols_result = cols.Sum();

    // get the offsets
    var offsets = GetOffsets(rows, cols);

    // fill 'er up
    var result = new T[rows_result, cols_result];
    Fill(result, m, offsets);
    return result;
}

public int[] GetSliceRows<T>(T[,][,] m)
{
    var sliceRows = new int[m.GetLength(0)];
    var segments = m.GetLength(1);
    for (var i = 0; i < sliceRows.Length; i++)
    {
        sliceRows[i] = Enumerable.Range(0, segments)
            .Select(j => m[i, j].GetLength(0))
            .Max();
    }
    return sliceRows;
}

public int[] GetSliceCols<T>(T[,][,] m)
{
    var sliceCols = new int[m.GetLength(1)];
    var segments = m.GetLength(0);
    for (var j = 0; j < sliceCols.Length; j++)
    {
        sliceCols[j] = Enumerable.Range(0, segments)
            .Select(i => m[i, j].GetLength(1))
            .Max();
    }
    return sliceCols;
}

public Tuple<int, int>[,] GetOffsets(int[] rows, int[] cols)
{
    var offsets = new Tuple<int, int>[rows.Length, cols.Length];
    for (var i = 0; i < rows.Length; i++)
        for (var j = 0; j < cols.Length; j++)
            offsets[i, j] = Tuple.Create(
                rows.Take(i).Sum(),
                cols.Take(j).Sum()
            );
    return offsets;
}

public void Fill<T>(T[,] result, T[,][,] m, Tuple<int, int>[,] offsets)
{
    for (var i = 0; i < m.GetLength(0); i++)
        for (var j = 0; j < m.GetLength(1); j++)
            Fill(result, m[i, j], offsets[i, j]);
}

public void Fill<T>(T[,] result, T[,] source, Tuple<int, int> offset)
{
    for (var i = 0; i < source.GetLength(0); i++)
        for (var j = 0; j < source.GetLength(1); j++)
            result[offset.Item1 + i, offset.Item2 + j] = source[i, j];
}

#3


-1  

I think you have to give array elements corresponding rowid and columnid to achieve the indexing issue of the outer matrix. Assuming you already have a Array to Matrix object conversion;

我认为你必须给出对应rowid和columnid的数组元素来实现外部矩阵的索引问题。假设您已经有一个Array to Matrix对象转换;

Being not sure if I undestood the rules correctly, but here is what I implemented so far:

不确定我是否正确地遵守了规则,但这是我到目前为止实施的内容:

I implemented Matrix and MatrixList classes as follows:

我实现了Matrix和MatrixList类,如下所示:

    public class Matrix
    {
        public int row { get; set; }
        public int column { get; set; }
        public double value { get; set; }
    }

    public class MatrixList
    {
        public List<Matrix> matrixList = new List<Matrix>();
    }

Using those classes, I implemented the algorithm below:

使用这些类,我实现了以下算法:

        List<MatrixList> matricesMatrix = new List<MatrixList>();
        init(matricesMatrix);

        int totalRows = 10;//as you stated, this is already known
        int totalColumns = 10;//as you stated, this is already known


        List<Matrix> ResultMatrix = new List<Matrix>();

        foreach (MatrixList matrixListItem in matricesMatrix)
        {
            for (int i = 0; i < totalRows; i++)
            {
                List<Matrix> matrixItemList = matrixListItem.matrixList.FindAll(s => s.row == i);

                foreach(Matrix matrixItem in matrixItemList)

                for (int j = 0; j < totalColumns; j++)
                {
                    if (matrixItem.column == j)
                        ResultMatrix.Add(new Matrix { row = i, column = j, value = matrixItem.value });
                }
            }              
        }

where init is a method to fill the objects, implemented as follows:

其中init是一个填充对象的方法,实现如下:

    private void init(List<MatrixList> matricesMatrix)
    {
        MatrixList ml = new MatrixList();
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                ml.matrixList.Add(new Matrix { row = i, column = j, value = i + j });
            }
        }
        matricesMatrix.Add(ml);
    }

I was on a windows forms dummy app, so used a richtextbox to test the code above.

我在一个Windows窗体虚拟应用程序,所以使用richtextbox来测试上面的代码。

        for (int i = 0; i < totalRows; i++)
        {
            foreach (Matrix item in ResultMatrix)
            {
                if (item.row == i)
                {
                    for (int j = 0; j < totalColumns; j++)
                        if (item.column == j)
                            richTextBox1.Text += item.value + " ";
                }
            }
            richTextBox1.Text += Environment.NewLine;
        }

and the result is:

结果是:

0 1 2 3 4 5 6 7 8 9 

1 2 3 4 5 6 7 8 9 10 

2 3 4 5 6 7 8 9 10 11 

3 4 5 6 7 8 9 10 11 12 

4 5 6 7 8 9 10 11 12 13 

5 6 7 8 9 10 11 12 13 14 

6 7 8 9 10 11 12 13 14 15 

7 8 9 10 11 12 13 14 15 16 

8 9 10 11 12 13 14 15 16 17 

9 10 11 12 13 14 15 16 17 18 

I don't have much time to give pretty numbers to array items to show beriefly at the moment, but I think you can get the idea.

我没有太多时间给阵列项目提供漂亮的数字,以便在此刻显示出来,但我认为你可以得到这个想法。

#1


4  

I started with a simple Matrix class to hold the double[,]s. Nothing too fancy, just a simple array-of-arrays with a row and column count and array accessor.

我开始使用一个简单的Matrix类来保存double [,] s。没有什么太花哨的,只是一个简单的数组数组,带有行数和列数以及数组访问器。

class Matrix<T>
{
    public int Rows { get; private set; }
    public int Cols { get; private set; }

    private T[,] mat;

    public Matrix(int rowCount, int colCount)
    {
        Rows = rowCount;
        Cols = colCount;
        mat = new T[Rows, Cols];
    }

    public T this[int r, int c]
    {
        get { return mat[r, c]; }
        set { mat[r, c] = value; }
    }
}

Your second case looks more difficult (and like a better test of correctness) than the first, so I set up a metamatrix to match that.

你的第二种情况比第一种情况看起来更难(并且更像是对正确性的更好测试),所以我设置了一个与之匹配的元矩阵。

public static Matrix<double[,]> BuildMetaMatrix()
{
    Matrix<double[,]> m = new Matrix<double[,]>(2, 2);

    m[0, 0] = new double[,]
    {
        { 1 }
    };

    m[0, 1] = new double[,]
    {
        { 3, 3, 3 },
        { 3, 3, 3 },
        { 3, 3, 3 }
    };

    m[1, 0] = new double[,]
    {
        { 2, 2 },
        { 2, 2 }
    };

    m[1, 1] = new double[,]
    {
        {4, 4, 4, 4},
        {4, 4, 4, 4},
        {4, 4, 4, 4},
        {4, 4, 4, 4}
    };

    return m;
}

For convenience, I made a Place function that puts one matrix into another one at the given location.

为方便起见,我创建了一个Place函数,它将一个矩阵放在给定位置的另一个矩阵中。

static void Place(double[,] src, double[,] dest, int destR, int destC)
{
    for (int row = 0; row < src.GetLength(ROW_DIM); row++)
    {
        for (int col = 0; col < src.GetLength(COL_DIM); col++)
        {
            dest[row + destR, col + destC] = src[row, col];
        }
    }
}

The magic numbers fed into GetLength() were just asking for mistakes, so I defined some constants for them (ROW_DIM = 0 and COL_DIM = 1). I decided to handle the padding by figuring out how wide a column is and how tall a row is and skipping any extra elements after Place()ing the sub-matrix in. A GetRowHeight() and GetColWidth() method figure out the values.

输入GetLength()的神奇数字只是要求错误,所以我为它们定义了一些常量(ROW_DIM = 0和COL_DIM = 1)。我决定通过计算列的宽度和行的高度来处理填充,并在Place()子矩阵之后跳过任何额外的元素.GetRowHeight()和GetColWidth()方法计算出值。

public static int GetRowHeight(Matrix<double[,]> m, int row)
{
    int maxSeen = 0;

    for (int col = 0; col < m.Cols; col++)
    {
        if (m[row, col].GetLength(ROW_DIM) > maxSeen)
        {
            maxSeen = m[row, col].GetLength(ROW_DIM);
        }
    }

    return maxSeen;
}

public static int GetColWidth(Matrix<double[,]> m, int col)
{
    int maxSeen = 0;

    for (int row = 0; row < m.Rows; row++)
    {
        if (m[row, col].GetLength(COL_DIM) > maxSeen)
        {
            maxSeen = m[row, col].GetLength(COL_DIM);
        }
    }

    return maxSeen;
}

A Flatten() function loops through all the sub-matrices, Place()ing them at the appropriate row and column in a new matrix. It updates the next row and column after each Place() using the GetRowHeight() and GetColWidth() functions.

Flatten()函数循环遍历所有子矩阵,将它们放置在新矩阵中的适当行和列上。它使用GetRowHeight()和GetColWidth()函数更新每个Place()之后的下一行和列。

Matrix<double> Flatten(Matrix<Matrix<double>> src)
{
    // (7, 6) == (this.TotalRows(), this.TotalColumns())
    // from your code.
    Matrix<double> dest = new Matrix<double>(7, 6);

    int nextRow = 0;
    int nextCol = 0;

    for (int row = 0; row < src.Rows; row++)
    {
        for (int col = 0; col < src.Rows; col++)
        {
            dest.Place(src[row, col], nextRow, nextCol);
            nextCol += GetColWidth(src, col);
        }
        nextRow += GetRowHeight(src, row);
        nextCol = 0;
    }

    return dest;
}

A little glue to test it out...

一点胶水来测试它...

static void Main(string[] args)
{
    Matrix<double[,]> src = BuildMetaMatrix();
    double[,] dest = Flatten(src);

    Print(dest);
    Console.ReadLine();
}

static void Print(double[,] matrix)
{
    for (int row = 0; row < matrix.GetLength(ROW_DIM); row++)
    {
        for (int col = 0; col < matrix.GetLength(COL_DIM); col++)
        {
            Console.Write(matrix[row, col] + "\t");
        }
        Console.Write("\n");
    }
}

...and you get an output just like your second case with all the oddly fitting matrices and 0s in the empty places.*

......你得到的输出就像你的第二个案例一样,所有奇怪的拟合矩阵和空位的0。*

1       0       3       3       3       0
0       0       3       3       3       0
0       0       3       3       3       0
2       2       4       4       4       4
2       2       4       4       4       4
0       0       4       4       4       4
0       0       4       4       4       4

*The destination matrix gets its values initialized to default(double), which happens to be 0 (the value you wanted). If you need something other than default(double) for the empty places, you can probably get them by iterating over the new matrix and writing the new default value everywhere before Flatten()ing the metamatrix.

*目标矩阵将其值初始化为默认值(double),恰好为0(您想要的值)。如果您需要除默认值(双精度数)以外的空位置,则可以通过迭代新矩阵并在Flatten()处理元矩阵之前的任何位置写入新的默认值来获取它们。

(Thanks to Jeff Mercado for pointing out that multidimensional arrays' GetLength() method can be used to find their dimensions.)

(感谢Jeff Mercado指出可以使用多维数组的GetLength()方法来查找它们的尺寸。)

#2


1  

I think it would be beneficial to you to break up the solution into the quadrants you are trying to fill. This will all be under the assumption that we will only be combining 4 matrices in this 2x2 configuration. The same strategies explined here can be applied to other dimensions of matrices to be combined.

我认为将解决方案分解为您想要填充的象限会对您有所帮助。这一切都假设我们将只在这个2x2配置中组合4个矩阵。这里所示的相同策略可以应用于要组合的矩阵的其他维度。

So given 4 matrices A, B, C and D, we will try to build a resulting matrix in this arrangement:

因此,给定4个矩阵A,B,C和D,我们将尝试在这种安排中构建一个结果矩阵:

+---+---+
| A | B |
+---+---+
| C | D |
+---+---+

Before we can start, we will need to figure out the dimensions of the final result. This should hopefully make sense. We'll have a top half, bottom half, left half and right half.

在我们开始之前,我们需要弄清楚最终结果的维度。这应该是有道理的。我们将有一个上半部分,下半部分,左半部分和右半部分。

rows_top    = max(rows_A, rows_B)
rows_bottom = max(rows_C, rows_D)
rows_result = rows_top + rows_bottom

cols_left   = max(cols_A, cols_C)
cols_right  = max(cols_B, cols_D)
cols_result = cols_left + cols_right

Then we will want to consider which regions of the result matrix we want to copy each of the 4 matrices. Considering the origin at the top-left, everything on the right half will be shifted over by the size of the left half, everything on the bottom half will be shifted over by the size of the top half. The offsets for each of the matrices would be:

然后我们将要考虑结果矩阵的哪些区域要复制4个矩阵中的每一个。考虑到左上角的原点,右半部分的一切都会被左半部分的大小移动,下半部分的一切都会被上半部分的大小移动。每个矩阵的偏移量将是:

offset_A = (0, 0)
offset_B = (0, cols_left)
offset_C = (rows_top, 0)
offset_D = (rows_top, cols_left)

Now with all this information, we can start building up the result matrix. Just copy over the values from each matrix to the result, with the offsets applied.

现在有了所有这些信息,我们就可以开始构建结果矩阵了。只需将每个矩阵的值复制到结果中,并应用偏移量。

So in code, I would do this:

所以在代码中,我会这样做:

// I'm just going to use plain 2D arrays here
public T[,] Combine<T>(T[,] a, T[,] b, T[,] c, T[,] d)
{
    // get the total rows
    var rows_top    = Math.Max(a.GetLength(0), b.GetLength(0));
    var rows_bottom = Math.Max(c.GetLength(0), d.GetLength(0));
    var rows_result = rows_top + rows_bottom;

    // get the total columns
    var cols_left   = Math.Max(a.GetLength(1), c.GetLength(1));
    var cols_right  = Math.Max(b.GetLength(1), d.GetLength(1));
    var cols_result = cols_left + cols_right;

    // get the offsets
    var offset_a = Tuple.Create(0, 0);
    var offset_b = Tuple.Create(0, cols_left);
    var offset_c = Tuple.Create(rows_top, 0);
    var offset_d = Tuple.Create(rows_top, cols_left);

    // fill 'er up
    var result = new T[rows_result, cols_result];
    Fill(result, a, offset_a);
    Fill(result, b, offset_b);
    Fill(result, c, offset_c);
    Fill(result, d, offset_d);
    return result;
}

public void Fill<T>(T[,] result, T[,] source, Tuple<int, int> offset)
{
    for (var i = 0; i < source.GetLength(0); i++)
        for (var j = 0; j < source.GetLength(1); j++)
            result[offset.Item1 + i, offset.Item2 + j] = source[i, j];
}

Then to demonstrate the result in terms of case 2:

然后根据案例2展示结果:

const string A = "A", B = "B", C = "C", D = "D";
var a = new string[1,1]
{
    { A },
};
var b = new string[3, 3]
{
    { B, B, B },
    { B, B, B },
    { B, B, B },
};
var c = new string[2, 2]
{
    { C, C },
    { C, C },
};
var d = new string[4, 4]
{
    { D, D, D, D },
    { D, D, D, D },
    { D, D, D, D },
    { D, D, D, D },
};
var result = Combine(a, b, c, d);

This of course can be generalized to any size matrix of matrices. The concept is the same in every step of the process.

这当然可以推广到任何大小的矩阵矩阵。这个概念在这个过程的每一步都是一样的。

Given m x n matrices, we will try to build a resulting matrix in this arrangement:

给定m×n矩阵,我们将尝试在这种安排中构建一个结果矩阵:

+-----+-----+-----+
| 0,0 | ... | 0,n |
+-----+-----+-----+
| ... |     | ... |
+-----+-----+-----+
| m,0 | ... | m,n |
+-----+-----+-----+
  1. Get the dimensions of each of the slices.

    获取每个切片的尺寸。

    rows_0 = max(rows_0_0, ..., rows_0_n)
    ...
    rows_m = max(rows_m_0, ..., rows_m_n)
    rows_result = sum(rows_0, ..., rows_m)
    
    cols_0 = max(cols_0_0, ..., cols_m_0)
    ...
    cols_n = max(cols_0_n, ..., cols_m_n)
    cols_result = sum(cols_0, ..., cols_m)
    
  2. Get the offsets for each of the matrices. Each vertical slice is offset to the left by the total amount of columns in the previous vertical slices. Each horizontal slice is offset to the down by the total amount of rows in the previous horizontal slices.

    获取每个矩阵的偏移量。每个垂直切片向左偏移前一垂直切片中的总列数。每个水平切片向下偏移前一水平切片中的总行数。

    offset_0_0 = (0, 0)
    ...
    offset_m_n = (sum(rows_0, ..., rows_m-1), sum(cols_0, ..., cols_n-1))
    

So now we can build up the result matrix.

所以现在我们可以建立结果矩阵。

public T[,] Combine<T>(T[,][,] m)
{
    // get the rows
    var rows = GetSliceRows(m);
    var rows_result = rows.Sum();

    // get the cols
    var cols = GetSliceCols(m);
    var cols_result = cols.Sum();

    // get the offsets
    var offsets = GetOffsets(rows, cols);

    // fill 'er up
    var result = new T[rows_result, cols_result];
    Fill(result, m, offsets);
    return result;
}

public int[] GetSliceRows<T>(T[,][,] m)
{
    var sliceRows = new int[m.GetLength(0)];
    var segments = m.GetLength(1);
    for (var i = 0; i < sliceRows.Length; i++)
    {
        sliceRows[i] = Enumerable.Range(0, segments)
            .Select(j => m[i, j].GetLength(0))
            .Max();
    }
    return sliceRows;
}

public int[] GetSliceCols<T>(T[,][,] m)
{
    var sliceCols = new int[m.GetLength(1)];
    var segments = m.GetLength(0);
    for (var j = 0; j < sliceCols.Length; j++)
    {
        sliceCols[j] = Enumerable.Range(0, segments)
            .Select(i => m[i, j].GetLength(1))
            .Max();
    }
    return sliceCols;
}

public Tuple<int, int>[,] GetOffsets(int[] rows, int[] cols)
{
    var offsets = new Tuple<int, int>[rows.Length, cols.Length];
    for (var i = 0; i < rows.Length; i++)
        for (var j = 0; j < cols.Length; j++)
            offsets[i, j] = Tuple.Create(
                rows.Take(i).Sum(),
                cols.Take(j).Sum()
            );
    return offsets;
}

public void Fill<T>(T[,] result, T[,][,] m, Tuple<int, int>[,] offsets)
{
    for (var i = 0; i < m.GetLength(0); i++)
        for (var j = 0; j < m.GetLength(1); j++)
            Fill(result, m[i, j], offsets[i, j]);
}

public void Fill<T>(T[,] result, T[,] source, Tuple<int, int> offset)
{
    for (var i = 0; i < source.GetLength(0); i++)
        for (var j = 0; j < source.GetLength(1); j++)
            result[offset.Item1 + i, offset.Item2 + j] = source[i, j];
}

#3


-1  

I think you have to give array elements corresponding rowid and columnid to achieve the indexing issue of the outer matrix. Assuming you already have a Array to Matrix object conversion;

我认为你必须给出对应rowid和columnid的数组元素来实现外部矩阵的索引问题。假设您已经有一个Array to Matrix对象转换;

Being not sure if I undestood the rules correctly, but here is what I implemented so far:

不确定我是否正确地遵守了规则,但这是我到目前为止实施的内容:

I implemented Matrix and MatrixList classes as follows:

我实现了Matrix和MatrixList类,如下所示:

    public class Matrix
    {
        public int row { get; set; }
        public int column { get; set; }
        public double value { get; set; }
    }

    public class MatrixList
    {
        public List<Matrix> matrixList = new List<Matrix>();
    }

Using those classes, I implemented the algorithm below:

使用这些类,我实现了以下算法:

        List<MatrixList> matricesMatrix = new List<MatrixList>();
        init(matricesMatrix);

        int totalRows = 10;//as you stated, this is already known
        int totalColumns = 10;//as you stated, this is already known


        List<Matrix> ResultMatrix = new List<Matrix>();

        foreach (MatrixList matrixListItem in matricesMatrix)
        {
            for (int i = 0; i < totalRows; i++)
            {
                List<Matrix> matrixItemList = matrixListItem.matrixList.FindAll(s => s.row == i);

                foreach(Matrix matrixItem in matrixItemList)

                for (int j = 0; j < totalColumns; j++)
                {
                    if (matrixItem.column == j)
                        ResultMatrix.Add(new Matrix { row = i, column = j, value = matrixItem.value });
                }
            }              
        }

where init is a method to fill the objects, implemented as follows:

其中init是一个填充对象的方法,实现如下:

    private void init(List<MatrixList> matricesMatrix)
    {
        MatrixList ml = new MatrixList();
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                ml.matrixList.Add(new Matrix { row = i, column = j, value = i + j });
            }
        }
        matricesMatrix.Add(ml);
    }

I was on a windows forms dummy app, so used a richtextbox to test the code above.

我在一个Windows窗体虚拟应用程序,所以使用richtextbox来测试上面的代码。

        for (int i = 0; i < totalRows; i++)
        {
            foreach (Matrix item in ResultMatrix)
            {
                if (item.row == i)
                {
                    for (int j = 0; j < totalColumns; j++)
                        if (item.column == j)
                            richTextBox1.Text += item.value + " ";
                }
            }
            richTextBox1.Text += Environment.NewLine;
        }

and the result is:

结果是:

0 1 2 3 4 5 6 7 8 9 

1 2 3 4 5 6 7 8 9 10 

2 3 4 5 6 7 8 9 10 11 

3 4 5 6 7 8 9 10 11 12 

4 5 6 7 8 9 10 11 12 13 

5 6 7 8 9 10 11 12 13 14 

6 7 8 9 10 11 12 13 14 15 

7 8 9 10 11 12 13 14 15 16 

8 9 10 11 12 13 14 15 16 17 

9 10 11 12 13 14 15 16 17 18 

I don't have much time to give pretty numbers to array items to show beriefly at the moment, but I think you can get the idea.

我没有太多时间给阵列项目提供漂亮的数字,以便在此刻显示出来,但我认为你可以得到这个想法。