Build a datatable from other datatables

0

Imagine that we have 3 datatables , each with a different number of rows,

For example:

DATATABLE A
fila 1 - "a1"
fila 2 - "a2"

DATATABLE B
fila 1 - "b1"
fila 2 - "b2"
fila 3 - "b3"

DATATABLE C
fila 1 - "c1"
fila 2 - "c2"

How can I build a method in C # or VB.NET that returns another DataTable with a field that includes a row of each of the 3 datatables with all possible combinations?

That is, I want to get the following result:

DATATABLE RESULTANTE
fila 1 "a1b1c1"
fila 2 "a1b1c2"
fila 3 "a1b2c1"
fila 4 "a1b2c2"
fila 5 "a1b3c1"
fila 6 "a1b3c2"
fila 7 "a2b1c1"
fila 8 "a2b1c2"
fila 9 "a2b2c1"
fila 10 "a2b2c2"
fila 11 "a2b3c1"
fila 12 "a2b3c2"

If you notice, the resulting rows are the result of multiplying the row numbers of each datatable (a b c), but what I can not do is to make a method that results in exposed. I imagine that you have to use recursion, but no matter how many laps I give you, I do not get it.

I want the method to be valid for more combinations, that is, that you do not really care about the number of tables involved or the number of rows in each table, the method must be able to obtain all possible combinations.

    
asked by Mario Rodríguez 06.04.2017 в 10:00
source

2 answers

0

Such a thing can help you, you can change the string object to any object you need and use the operative you need to implement within the second for:

    public static List<string> gComb(List<List<string>> list)
    {
        List<string> res = new List<string>();
        List<string> first = list.First();
        List<List<string>> aux = list.Skip(1).ToList();

        if (list.Count > 1)
        {
            foreach (string s in gComb(aux))
            {
                foreach (string st in first)
                {
                    res.Add(st + ", " + s);
                }
            }
            return res;
        }
        else {
            return list.First();
        }
    }

Use linQ and recursion.

    
answered by 07.04.2017 / 12:16
source
2

Although the question itself does not show much effort, I will try to give an answer because I think the topic is interesting.

What you are looking for in mathematics is called Cartesian Product and in SQL Cross Join, and being known the number of tables is Simple to solve using linq:

var producto = 
from primero in s1 
from segundo in s2 
from tercero in s3 
select new[] {first, second, third};

This makes the Cartesian product of 3 IEnumerables .

When the ticket listing number is unknown, things get complicated but through Linq it is also possible to do so. I add an example below that makes use of an extension method to make the Cartesian product of an unknown number of, in this example, arrays:

Extension method

public static IEnumerable<IEnumerable<T>> ProductoCartesiano<T>(this IEnumerable<IEnumerable<T>> secuencias)
{
    IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() };
    foreach (var secuencia in secuencias)
    {
        var s = secuencia; 
        // usando SelectMany
        resultado = resultado.SelectMany(s1 => s, (s1, s2) => (s1.Concat(new[] { s2 }))).ToArray(); //lambda

        //Usando Linq
        //resultado =
        //from seq in resultado
        //from item in s
        //select secuencia.Concat(new[] { item }).ToArray();
    }
    return resultado;
}

Example

string[] data1 = new string[2] { "a1", "a2" };
string[] data2 = new string[3] { "b1", "b2", "b3" };
string[] data3 = new string[2] { "c1", "c2" };

List<string[]> listaDatos = new List<string[]>();
listaDatos.Add(data1);
listaDatos.Add(data2);
listaDatos.Add(data3);

var productoCartesiano = listaDatos.ProductoCartesiano().Select(x=>String.Join(",",x)).ToList();

To finish, I do not want to attribute the merit of this solution, I have only adapted the code a bit. The brain is Mr. Eric Lippert and he explains it perfectly in your MSDN Blog

    
answered by 06.04.2017 в 17:03