Pass elements from a Listbox to a two-dimensional array in C #

0

I want to calculate the average of this matrix but only classes, based on this matrix:

2 4 4 0 0 
1 3 5 5 5
1 5 3 2 4
2 6 2 1 3
2 5 3 0 1

The first column indicates the number of the class that belongs to the row, the first row only indicates the number of classes, the number of objects and the number of attributes.

That is:

2 4 4 0 0 //matriz[0,0] numero de clases, matriz[0,1] numero de objetos, matriz[0,2] numero de atributos
1 3 5 5 5 //matriz[1,0] clase a la que pertenece la fila osea clase 1
1 5 3 2 4 //matriz[2,0] clase a la que pertenece la fila osea clase 1
2 6 2 1 3 //matriz[3,0] clase a la que pertenece la fila osea clase 2
2 5 3 0 1 //matriz[4,0] clase a la que pertenece la fila osea clase 2

In a nutshell I want the average of each class per column.

This is my code but it only takes the average from the entire matrix.

 int x = showdata.Items.Count;
        int y = showdata.Items[0].ToString().Split().Count();
        matriz = new Int32[x, y];
        contCol = new Int32[x];

        for (int i = 0; i < matriz.GetLength(0); i++)
        {
            for (int j = 0; j < matriz.GetLength(1); j++)
            {
                matriz[i, j] = Convert.ToInt32(showdata.Items[i].ToString().Split()[j]);
            }
        }

        label4.Text = Convert.ToString(cont);

        for (int i = 0; i < y; i++)
        {
            for (int j = 1; j < x; j++)
            {
                if (i == 0)
                {
                    contCol[cont] = matriz[j, i];



                    listBox2.Items.Add(contCol[cont]);

                }


            }

            cont++;
        }


        int f = listBox2.Items.Count;
        contCol = new Int32[f];

        for (int i = 0; i < contCol.GetLength(0); i++)
            contCol[i] = Convert.ToInt32(listBox2.Items[i].ToString());



        cont = 0;
        label4.Text = Convert.ToString(contCol[0]);
        for (int i=0;i<y;i++)
        {

            suma = 0;
            if (contCol[cont] == i)
            {

                if (i > 0)
                {

                    for (int j = 0; j < x; j++)
                    {
                        if (contCol[cont] == j)
                        {
                            if (j > 0)
                                suma = suma + matriz[j, i];
                        }

                    }
                }
                promedio = (suma / (x - 1));
                if (promedio != 0)
                    listcentroide.Items.Add(promedio);

            }
        }
    
asked by Angel Sanchez Lugo 14.10.2017 в 03:28
source

1 answer

1

As Flxtr suggests in a comment, including the expected result in your question helps you find an answer, not only to those who can answer but to yourself.

The best way to do this is to use unit tests. Basically, a unit test is a code that exercises the algorithm that you want to develop and verifies that its result is the expected one. Here you can find more information on the subject.

I have written the following test, I hope it fulfills what you are looking for. You get a dictionary whose key is the column number and its value another dictionary, whose key is the class and its value the average. So, find the average in the x column for the class and it will be resultado[x][y] :

public void TestObtenerPromediosPorClasePorColumna()
{
    int[,] matriz = {
        {2, 4, 4, 0, 0},
        {1, 3, 5, 5, 5},
        {1, 5, 3, 2, 4},
        {2, 6, 2, 1, 3},
        {2, 5, 3, 0, 1}
    };

    var resultado = ObtenerPromedios(matriz);

    var promedioColumna1Clase1 = resultado[1][1];
    Assert.AreEqual(4.0, promedioColumna1Clase1);
    var promedioColumna1Clase2 = resultado[1][2];
    Assert.AreEqual(5.5, promedioColumna1Clase2);
    var promedioColumna2Clase1 = resultado[2][1];
    Assert.AreEqual(4.0, promedioColumna2Clase1);
    var promedioColumna2Clase2 = resultado[2][2];
    Assert.AreEqual(2.5, promedioColumna2Clase2);
}

Once the objective is established, we can write the algorithm. When doing so, it is highly recommended to use variables with explanatory names, such as numeroDeFilas or promediosPorClase . I leave here the algorithm that gets the expected result:

private Dictionary<int, Dictionary<int, double>> ObtenerPromedios(int[,] matriz)
{
    var resultado = new Dictionary<int, Dictionary<int, double>>();

    int numeroDeFilas = matriz.GetLength(0);
    int numeroDeColumnas = matriz.GetLength(1);

    for (int ncol = 0; ncol < numeroDeColumnas; ncol++)
    {
        var valoresPorClase = new Dictionary<int, List<int>>();

        for (int nfila = 1; nfila < numeroDeFilas; nfila++)
        {
            int valor = matriz[nfila, ncol];
            int clase = matriz[nfila, 0];

            if (!valoresPorClase.ContainsKey(clase))
            {
                valoresPorClase.Add(clase, new List<int>());
            }

            valoresPorClase[clase].Add(valor);
        }

        var promediosPorClase = new Dictionary<int, double>();
        foreach (KeyValuePair<int, List<int>> valores in valoresPorClase)
        {
            int clase = valores.Key;
            double promedio = valores.Value.Average();
            promediosPorClase.Add(clase, promedio);
        }

        resultado.Add(ncol, promediosPorClase);
    }

    return resultado;
}
    
answered by 16.10.2017 в 12:28