Find data that are only in a list (two list (of T)

Find data that are only in a list (two list (of T)

cyranobb30
Advocate Advocate
997 Views
6 Replies
Message 1 of 7

Find data that are only in a list (two list (of T)

cyranobb30
Advocate
Advocate
'Hello, I need your help for the following

 

'I have 2 lists.

Public ListBD As New List(Of Tuple(Of String, String, String))
Public ListAcc As New List(Of Tuple(Of String, Double))

 

I have linked them by the first item (description). Now I get the description field of ListBD, code of ListBD and Quantity of ListAcc. This works perfect

Dim RptCargador = From Datos In ListBD, Datos1 In ListAcc
Where Datos.Item1 = Datos1.Item1
Order By Datos.Item3
Select Descripcion = Datos.Item3, Codigo = Datos.Item2, Cantidad = Datos1.Item2
Libro.Sheets(1).cells(1, 1) = "Código"
Libro.Sheets(1).cells(1, 2) = "Cantidad"
Libro.Sheets(1).cells(1, 3) = "Descripción de Artículo"
For Each valor In RptCargador
Libro.Sheets(1).cells(i, 1) = valor.Codigo
Libro.Sheets(1).cells(i, 2) = valor.Cantidad
Libro.Sheets(1).cells(i, 3) = valor.Descripcion
i = i + 1
Next

 

'What is what I need.
'I need the data that does not match the item1 of ListAcc and the item1 of ListBD
'In the attached file there is an example.
I have solved it by doing one cycle inside another. But this takes a long time, it is very slow. This is how I did it. I hope you can give me a better shape.

#Region "Datos No Encontrados"
Dim RptCargador1 = From Datos In ListAcc
Select Datos.Item1, Datos.Item2

For Each valor In RptCargador1
Dim diferente As Boolean : Dim igual As Boolean

Dim RptCargador2 = From Datos1 In ListBD
Select Datos1.Item1
diferente = False : igual = False
For Each valor2 In RptCargador2
If valor.Item1 <> valor2 Then
diferente = True
Else
igual = True
End If
Next
If diferente = True And igual = False Then
Libro.Sheets(1).cells(i, 2) = valor.Item2
Libro.Sheets(1).cells(i, 3) = valor.Item1
i = i + 1
End If

Next
#End Region

 

I hope you can give me a better shape. Maybe similar to the one I developed for the first part
Thank you

 

0 Likes
Accepted solutions (1)
998 Views
6 Replies
Replies (6)
Message 2 of 7

_gile
Consultant
Consultant

Hi,

 

Using keyed data structures as Dictionary<string, Tupe<string, string>> and Dictionary<string, double> should be more efficient than using lists of tuples



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 7

cyranobb30
Advocate
Advocate
Thank you very much. I use this one because it's the one I know, it's good for me, but in this case I do not know how to solve it. Later on I will invert what you mention
0 Likes
Message 4 of 7

_gile
Consultant
Consultant

Here's a little example (C# Console Application).

 

        static void Main()
        {
            var dictBd = new Dictionary<string, Tuple<string, string>>
            {
                ["hola"] = new Tuple<string, string>("1", "hola hola"),
                ["carro"] = new Tuple<string, string>("2", "carro carro"),
                ["nuevo"] = new Tuple<string, string>("5", "nuevo nuevo"),
                ["viejo"] = new Tuple<string, string>("7", "viejo viejo"),
                ["alto"] = new Tuple<string, string>("3", "alto alto"),
                ["bajo"] = new Tuple<string, string>("11", "bajo bajo")
            };

            var dictAcc = new Dictionary<string, double>
            {
                ["hola"] = 7,
                ["carro"] = 5,
                ["nuevo"] = 1,
                ["viejo"] = 70,
                ["alto"] = 22,
                ["bajo"] = 99,
                ["rico"] = 2,
                ["pobre"] = 14
            };

            var rptCargador = dictBd
                .Where(x => dictAcc.ContainsKey(x.Key))
                .OrderBy(x => x.Value.Item2)
                .Select(x => new { Descripcion = x.Value.Item2, Codigo = x.Value.Item1, Cantidad = dictAcc[x.Key] });
            foreach (var item in rptCargador)
            {
                Console.WriteLine($"{item.Descripcion} {item.Codigo} {item.Cantidad}");
            }

            Console.WriteLine("Datos No Encontrados");
            var rptCargador1 = dictAcc.Where(x => !dictBd.ContainsKey(x.Key));
            foreach (var item in rptCargador1)
            {
                Console.WriteLine($"{item.Key} {item.Value}");
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 7

cyranobb30
Advocate
Advocate
Hello
Thanks for your help.
I have never used C # or C ++. I'm an agricultural engineer and I only know a little bit about vb.net.
I tried to convert c # to vb.net, but I could not. This is what I achieved. Talvéz you can help me with what is missing. Thank you.
Also if you know where I can see examples like this to guide me.
Greetings (also attached image)

#Region "Prueba en C#"
'Agregando Datos a un Dictionary
' Add four entries.

Dim BD As New Dictionary(Of String, Tuple(Of String, String))
BD.Add("hola", New Tuple(Of String, String)("1", "hola hola"))
BD.Add("carro", New Tuple(Of String, String)("2", "carro carro"))
BD.Add("nuevo", New Tuple(Of String, String)("5", "nuevo nuevo"))
BD.Add("viejo", New Tuple(Of String, String)("7", "viejo viejo"))
BD.Add("alto", New Tuple(Of String, String)("3", "alto alto"))
BD.Add("bajo", New Tuple(Of String, String)("11", "bajo bajo"))

Dim Acc As New Dictionary(Of String, Integer)
Acc.Add("hola", 1)
Acc.Add("carro", 5)
Acc.Add("nuevo", 1)
Acc.Add("viejo", 70)
Acc.Add("alto", 22)
Acc.Add("bajo", 99)
Acc.Add("alto", 2)
Acc.Add("bajo", 14)

Dim rptCargador8 = BD.Where(Function(x) Acc.ContainsKey(x.Key)).OrderBy(x >= x.Value.Item2).Select(x >= New Descripcion = x.Value.Item2, Codigo = x.Value.Item1, Cantidad = dictAcc(x.Key)

'Datos Encontrados
For Each item In rptCargador8
MsgBox(item.Descripcion & item.Codigo & item.Cantidad)
Next
'Datos NO Encontrados

Dim rptCargador10 = Acc.Where(Function(x) Not BD.ContainsKey(x.Key))
For Each item In rptCargador10
' Console.WriteLine($"{item.Key} {item.Value}")
MsgBox(item.Key & item.Value)
Next
#End Region
0 Likes
Message 6 of 7

_gile
Consultant
Consultant

Here's a VB conversion of the C# code I posted:

 

    Sub Main()
        Dim BD As New Dictionary(Of String, Tuple(Of String, String))
        BD.Add("hola", New Tuple(Of String, String)("1", "hola hola"))
        BD.Add("carro", New Tuple(Of String, String)("2", "carro carro"))
        BD.Add("nuevo", New Tuple(Of String, String)("5", "nuevo nuevo"))
        BD.Add("viejo", New Tuple(Of String, String)("7", "viejo viejo"))
        BD.Add("alto", New Tuple(Of String, String)("3", "alto alto"))
        BD.Add("bajo", New Tuple(Of String, String)("11", "bajo bajo"))

        Dim Acc As New Dictionary(Of String, Integer)
        Acc.Add("hola", 1)
        Acc.Add("carro", 5)
        Acc.Add("nuevo", 1)
        Acc.Add("viejo", 70)
        Acc.Add("alto", 22)
        Acc.Add("bajo", 99)
        Acc.Add("rico", 2)
        Acc.Add("pobre", 14)

        Dim rptCargador = BD _
            .Where(Function(x) Acc.ContainsKey(x.Key)) _
            .OrderBy(Function(x) x.Value.Item2) _
            .Select(Function(x) New With {Key .Descripcion = x.Value.Item2, .Codigo = x.Value.Item1, .Cantidad = Acc(x.Key)})

        For Each item In rptCargador
            Console.WriteLine("{0} {1} {2}", item.Descripcion, item.Codigo, item.Cantidad)
        Next

        Console.WriteLine()
        Console.WriteLine("Datos No Encontrados")

        Dim rptCargador1 = Acc.Where(Function(x) Not BD.ContainsKey(x.Key))
        For Each item In rptCargador1
            Console.WriteLine("{0} {1}", item.Key, item.Value)
        Next
    End Sub

If you prefer the SQL syntax:

 

    Sub Main()
        Dim BD As New Dictionary(Of String, Tuple(Of String, String))
        BD.Add("hola", New Tuple(Of String, String)("1", "hola hola"))
        BD.Add("carro", New Tuple(Of String, String)("2", "carro carro"))
        BD.Add("nuevo", New Tuple(Of String, String)("5", "nuevo nuevo"))
        BD.Add("viejo", New Tuple(Of String, String)("7", "viejo viejo"))
        BD.Add("alto", New Tuple(Of String, String)("3", "alto alto"))
        BD.Add("bajo", New Tuple(Of String, String)("11", "bajo bajo"))

        Dim Acc As New Dictionary(Of String, Integer)
        Acc.Add("hola", 1)
        Acc.Add("carro", 5)
        Acc.Add("nuevo", 1)
        Acc.Add("viejo", 70)
        Acc.Add("alto", 22)
        Acc.Add("bajo", 99)
        Acc.Add("rico", 2)
        Acc.Add("pobre", 14)

        Dim rptCargador =
            From x In BD
            Where Acc.ContainsKey(x.Key)
            Order By x.Value.Item2
            Select Descripcion = x.Value.Item2, Codigo = x.Value.Item1, Cantidad = Acc(x.Key)

        For Each item In rptCargador
            Console.WriteLine("{0} {1} {2}", item.Descripcion, item.Codigo, item.Cantidad)
        Next

        Console.WriteLine()
        Console.WriteLine("Datos No Encontrados")

        Dim rptCargador1 =
            From x In Acc
            Where Not BD.ContainsKey(x.Key)
            Select x

        For Each item In rptCargador1
            Console.WriteLine("{0} {1}", item.Key, item.Value)
        Next
    End Sub


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 7

cyranobb30
Advocate
Advocate
Accepted solution
friend
Thank you very much for your help. I do not understand how there are people who help others in this way.
With your help I have solved it and also learned a bit of Dictionary.
Many blessings
This is how I was left

Dim BD As New Dictionary(Of String, Tuple(Of String, String))
BD.Add("hola", New Tuple(Of String, String)("1", "hola hola"))
BD.Add("carro", New Tuple(Of String, String)("2", "carro carro"))
BD.Add("nuevo", New Tuple(Of String, String)("5", "nuevo nuevo"))
BD.Add("viejo", New Tuple(Of String, String)("7", "viejo viejo"))
BD.Add("alto", New Tuple(Of String, String)("3", "alto alto"))
BD.Add("bajo", New Tuple(Of String, String)("11", "bajo bajo"))

Dim Acc As New Dictionary(Of String, Integer)
Acc.Add("hola", 1)
Acc.Add("carro", 5)
Acc.Add("nuevo", 1)
Acc.Add("viejo", 70)
Acc.Add("alto", 22)
Acc.Add("bajo", 99)
Acc.Add("rico", 2)
Acc.Add("pobre", 14)

'Datos Encontrados
Dim rptCargador8 = Acc.Where(Function(x) BD.ContainsKey(x.Key))
For Each item In rptCargador8
MsgBox("Código = " & BD.Item(item.Key).Item1 & " Cantidad = " & item.Value & " Descripción = " & BD.Item(item.Key).Item2)
Next
'Datos NO Encontrados
Dim rptCargador10 = Acc.Where(Function(x) Not BD.ContainsKey(x.Key))
For Each item In rptCargador10
MsgBox("Cantidad = " & item.Value & " Descripción = " & item.Key)
Next

 

0 Likes