Home > OS >  List(Of ClassA) contains a List(of ClassB) and in it a string. Check if the new string already exist
List(Of ClassA) contains a List(of ClassB) and in it a string. Check if the new string already exist

Time:09-16

I have a List(of ClassA) which includes a List(of ClassB). This contains a string called “heading”. I read in a new string using a text box. I want to check if the new string already exists.

My previous code works, but I think it can be done in a more elegant way. I find it a little difficult because I have this class construct. I created a new project for you and only copied the necessary – but reproducible – source code.

Form1.vb

Imports Microsoft.VisualBasic.ControlChars
Public NotInheritable Class FormMain
    Private allA As New List(Of ClassA)
    Private the_new_String As String = ""

    Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        allA.Add(New ClassA)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        For i As Integer = 0 To allA.Count - 1 Step 1
            For j As Integer = 0 To allA(i).allB.Count - 1 Step 1
                If allA(i).allB(j).Heading = the_new_String Then
                    MessageBox.Show($"Diesen Titel gibt es bereits.{NewLine}This title already exists.",
                                    "",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information)
                    Return
                End If
            Next
        Next
    End Sub

    Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
        the_new_String = TextBox1.Text
    End Sub
End Class

ClassA.vb

Public Class ClassA
    Public allB As New List(Of ClassB)

    Public Sub New()
        allB.Add(New ClassB())
    End Sub
End Class

ClassB.vb

Public Class ClassB
    Public Heading As String = "Test"
End Class

CodePudding user response:

If allA.Any(Function(a) a.allB.Any(Function(b) b.Heading = the_new_String)) Then
    'The specified text already exists.
End If

CodePudding user response:

There's nothing wrong with the nested loop that you have. Anything else you do will ultimately compile down to the same nested loop (although the loop statements would likely be hidden in a Linq function call). For example, in the other answer posted, each Any call is hiding a loop.

As another alternative, you could consider using SelectMany, which is the Linq routine for flattening a hierarchy.

The result would be,

If allA.SelectMany(Function(a) a.allB.Select(Function(b) b.Heading)) _
       .Any(Function(heading) heading = testString) Then
    'Proposed heading already exists
End If

I believe this would end up with similar algorithmic efficiency to your original code or to the code in the other answer. SelectMany, Select, and Any should all use deferred execution, so I think it would break out of the implicit nested loop as soon as a match is found without extra iterations. (It's easy to reason about the set operations that Linq will give you, but it's not necessarily easy to identify the loop complexity that hides behind the statements, especially when some Linq functions will evaluate eagerly and others will defer.)

  • Related