Results 1 to 10 of 10

Thread: LINQ question

  1. #1

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    LINQ question

    I'm a LINQ newbie...seen lots of code examples here but have no clue how to do it.

    Let's say I've got this list(of string)...

    Code:
            BookAbbrList = New List(Of List(Of String)) From {
                New List(Of String)({"Genesis", "gen"}),
                New List(Of String)({"Exodus", "exo"}),
                New List(Of String)({"Leviticus", "lev"}),
                New List(Of String)({"Numbers", "num"}),
                New List(Of String)({"Deuteronomy", "deu"}),
                New List(Of String)({"Joshua", "jos"}),
    How could I take the "abbreviations" - gen, exo, lev - and return the BOOK NAME...

    tia

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  2. #2
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,711

    Re: LINQ question

    I would personally use a Dictionary(Of String, String) and not use LINQ at all for this situation:
    Code:
    Dim bookAbbrList = New Dictionary(Of String, String)() From {
        { "gen", "Genesis" },
        { "exo", "Exodus" },
        { "lev", "Leviticus" },
        { "num", "Numbers" },
        { "deu", "Deuteronomy" },
        { "jos", "Joshua" }
    }
    
    Console.Write("Book Abbreviation: ")
    Dim abbreviation = Console.ReadLine()
    If (bookAbbrList.ContainsKey(abbreviation)) Then
        Dim fullName = bookAbbrList(abbreviation)
        Console.WriteLine(fullName)
    End If
    Example: https://dotnetfiddle.net/UaqKoj
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  3. #3

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: LINQ question

    @dday - thanks for that.

    I might put more items in the list - it might not be just two.

    Is there also a LINQ attack that would get to the "row" of data?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  4. #4
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,711

    Re: LINQ question

    In that case, you could still use LINQ. What you would be doing is querying items where the current item's list contains the abbreviation. Maybe something like this:
    Code:
    Dim bookAbbrList = New List(Of List(Of String)) From {
        New List(Of String)({"Genesis", "gen"}),
        New List(Of String)({"Exodus", "exo"}),
        New List(Of String)({"Leviticus", "lev"}),
        New List(Of String)({"Numbers", "num"}),
        New List(Of String)({"Deuteronomy", "deu"}),
        New List(Of String)({"Joshua", "jos"})
    }
    		
    Console.Write("Book Abbreviation: ")
    Dim abbreviation = Console.ReadLine()
    
    Dim match = bookAbbrList.FirstOrDefault(Function(record) record.Contains(abbreviation))
    If (match IsNot Nothing) Then
        Console.WriteLine(String.Join(",", match))
    End If
    Example: https://dotnetfiddle.net/WQZaVd

    Update
    To elaborate on my code a little bit, here it is broken down:
    • FirstOrDefault: Query the collection for the first instance that matches the predicate. If no match is returned, return Nothing
    • Function(record): The start of my predicate, indicating that record represents the current item in the iteration
    • record.Contains(abbreviation): The condition that is being used to return a Boolean value for the predicate. If true, then it will return record
    • If (match IsNot Nothing) Then: Since I used the FirstOrDefault method, I need to check if the returned value is Nothing because if it is, then that means nothing matched the condition in my predicate
    Last edited by dday9; Apr 5th, 2021 at 02:04 PM.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  5. #5
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: LINQ question

    Quote Originally Posted by szlamany View Post
    @dday - thanks for that.

    I might put more items in the list - it might not be just two.

    Is there also a LINQ attack that would get to the "row" of data?
    In that case, it sounds like you should be defining a dedicated type to represent a "row" and then creating a List(Of T) where T is that type. You can certainly write LINQ queries to do things with a list of lists but it's generally not something you would do for the type of data you seem to be working with.

  6. #6
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,040

    Re: LINQ question

    this isn't my Code
    I found this sample but can't remenber where, I was looking at the time for 'Linq Join'

    see if it helps
    Code:
    Public Class Form1
    
        Public Class Student
            Public Property Id As String
            Public Property StudentName As String
            Public Property GPA As String
        End Class
    
        Public Class StudentsSubject
            Public Property SubjectId As String
            Public Property StudentId As String
            Public Property Id As String
        End Class
    
        Public Class Subject
            Public Property Id As String
            Public Property SubjectName As String
        End Class
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim students As New List(Of Student)
            students.Add(New Student With {.Id = "1", .GPA = "GPA1", .StudentName = "John"})
            students.Add(New Student With {.Id = "2", .GPA = "GPA2", .StudentName = "Peter"})
            students.Add(New Student With {.Id = "3", .GPA = "GPA3", .StudentName = "Mary"})
    
            Dim subjects As New List(Of Subject)
            subjects.Add(New Subject With {.Id = "100", .SubjectName = "Maths"})
            subjects.Add(New Subject With {.Id = "200", .SubjectName = "Physics"})
    
            Dim studentsSubject As New List(Of StudentsSubject)
            studentsSubject.Add(New StudentsSubject With {.Id = "10", .StudentId = "1", .SubjectId = "100"})
            studentsSubject.Add(New StudentsSubject With {.Id = "20", .StudentId = "1", .SubjectId = "200"})
            studentsSubject.Add(New StudentsSubject With {.Id = "30", .StudentId = "2", .SubjectId = "100"})
            studentsSubject.Add(New StudentsSubject With {.Id = "40", .StudentId = "3", .SubjectId = "100"})
    
            Dim listOfStudents = From st In students
                                 Join ss In studentsSubject On ss.StudentId Equals st.Id
                                 Join sb In subjects On ss.SubjectId Equals sb.Id
                                 Select st.StudentName, st.GPA, sb.SubjectName
    
    
           
    
            Dim line As String = New String("-", 40)
    
            For Each s In listOfStudents
                Debug.WriteLine("{0} on {1}", s.StudentName, _
                   s.SubjectName)
            Next
    
            Dim res = From cust In students
             Group Join so In studentsSubject
               On so.StudentId Equals cust.Id
               Into MatchedOrders = Group
             From mo In MatchedOrders.DefaultIfEmpty()
            For Each r In res
                Debug.WriteLine("{0} on {1}", r.mo.StudentId, _
                 r.mo.SubjectId)
            Next
        End Sub
    
    End Class
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  7. #7

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: LINQ question

    Quote Originally Posted by jmcilhinney View Post
    In that case, it sounds like you should be defining a dedicated type to represent a "row" and then creating a List(Of T) where T is that type. You can certainly write LINQ queries to do things with a list of lists but it's generally not something you would do for the type of data you seem to be working with.
    I'm attempting to learn a little LINQ. And do it with a simple structure.

    So far what I dislike about the LINQ syntax is how bloated it is compared to hiding a loop on that list in a function that just returns the name. Then that code - calling that function - stays nice and neat. I guess LINQ experts would simply use the LINQ search in the "function" and keep the calling code tight anyway.

    I'm writing a one-off, one-time use program and was handed that list. Was about to write a loop to turn abbreviations into names - thought about using LINQ...

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: LINQ question

    Quote Originally Posted by szlamany View Post
    I'm a LINQ newbie...seen lots of code examples here but have no clue how to do it.

    Let's say I've got this list(of string)...

    Code:
            BookAbbrList = New List(Of List(Of String)) From {
                New List(Of String)({"Genesis", "gen"}),
                New List(Of String)({"Exodus", "exo"}),
                New List(Of String)({"Leviticus", "lev"}),
                New List(Of String)({"Numbers", "num"}),
                New List(Of String)({"Deuteronomy", "deu"}),
                New List(Of String)({"Joshua", "jos"}),
    How could I take the "abbreviations" - gen, exo, lev - and return the BOOK NAME...

    tia
    To address the question as asked:
    vb.net Code:
    1. Dim name = BookAbbrList.FirstOrDefault(Function(book) book(1) = abbreviation)?(0)
    The First, FirstOrDefault, Single and SingleOrDefault methods all work similarly but there's never a time that one isn't the only correct option and you should use that one based on your scenario.

    First: gets the first match and throws an exception if there are no matches.
    FirstOrDefault: gets the first match or Nothing if there is no match.
    Single: gets the only match and throws an exception if there are no matches or multiple matches.
    SingleOrDefault: gets the only match or Nothing if there is no match and throws an exception if there are multiple matches.

    If you use First or Single then you can do away with the null-coalescing operator (?) because the expression preceding it can never be Nothing.

  9. #9
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: LINQ question

    Quote Originally Posted by jmcilhinney View Post
    The First, FirstOrDefault, Single and SingleOrDefault methods all work similarly but there's never a time that one isn't the only correct option and you should use that one based on your scenario.

    First: gets the first match and throws an exception if there are no matches.
    FirstOrDefault: gets the first match or Nothing if there is no match.
    Single: gets the only match and throws an exception if there are no matches or multiple matches.
    SingleOrDefault: gets the only match or Nothing if there is no match and throws an exception if there are multiple matches.

    If you use First or Single then you can do away with the null-coalescing operator (?) because the expression preceding it can never be Nothing.
    I do tend to dwell on this a bit because a lot of people don't immediately see the difference or realise that it's important. The implementations of those four methods is effectively like this:
    vb.net Code:
    1. Imports System.Runtime.CompilerServices
    2.  
    3. Public Module EnumerableExtensions
    4.  
    5.     <Extension>
    6.     Public Function First(Of T)(source As IEnumerable(Of T), predicate As Predicate(Of T)) As T
    7.         For Each item In source
    8.             If predicate(item) Then
    9.                 Return item
    10.             End If
    11.         Next
    12.  
    13.         Throw New Exception()
    14.     End Function
    15.  
    16.     <Extension>
    17.     Public Function FirstOrDefault(Of T)(source As IEnumerable(Of T), predicate As Predicate(Of T)) As T
    18.         For Each item In source
    19.             If predicate(item) Then
    20.                 Return item
    21.             End If
    22.         Next
    23.  
    24.         Return Nothing
    25.     End Function
    26.  
    27.     <Extension>
    28.     Public Function [Single](Of T)(source As IEnumerable(Of T), predicate As Predicate(Of T)) As T
    29.         Dim matchFound = False
    30.         Dim match As T
    31.  
    32.         For Each item In source
    33.             If predicate(item) Then
    34.                 If matchFound Then
    35.                     Throw New Exception()
    36.                 End If
    37.  
    38.                 matchFound = True
    39.                 match = item
    40.             End If
    41.         Next
    42.  
    43.         If matchFound Then
    44.             Return match
    45.         End If
    46.  
    47.         Throw New Exception()
    48.     End Function
    49.  
    50.     <Extension>
    51.     Public Function SingleOrDefault(Of T)(source As IEnumerable(Of T), predicate As Predicate(Of T)) As T
    52.         Dim matchFound = False
    53.         Dim match As T
    54.  
    55.         For Each item In source
    56.             If predicate(item) Then
    57.                 If matchFound Then
    58.                     Throw New Exception()
    59.                 End If
    60.  
    61.                 matchFound = True
    62.                 match = item
    63.             End If
    64.         Next
    65.  
    66.         If matchFound Then
    67.             Return match
    68.         End If
    69.  
    70.         Return Nothing
    71.     End Function
    72.  
    73. End Module
    You just need to think about how you would write the code to do it long-hand to know which of the four methods you should choose. Note that First and FirstOrDeafult return as soon as a match is found while Single and SingleOrDefault continue enumerating to the end of the list or until a second match is found. This means that the former two might be much quicker for long lists but the latter two provide explicit validation where list items are supposed to be unique.

  10. #10

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: LINQ question

    @jmc - thanks - that explains it nicely. LINQ is no longer in the realm of "regex" to me!

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width