Click here to Skip to main content
15,884,298 members
Articles / Programming Languages / Visual Basic
Tip/Trick

LINQ Extension Methods for Rescue

Rate me:
Please Sign up or sign in to vote.
4.78/5 (10 votes)
2 May 2014CPOL4 min read 19.4K   144   19   3
LINQ Extensions methods that may help you a lot

Introduction

In this article I'll explain 9 extension methods that may help the developer very much specially when they 're doing queries in LINQy fashion.

Background

Language Integrated Query (LINQ) is a cool technologies for querying different data sources, when it shipped in .NET 3.5 it came with essential extension methods for projection, filtering, aggregation and so forth all of them are out of the box.

I faced many issues in some scenarios where I can't find a suitable method to achieve my goal. So i was thinking in the last few days to write some of the extension methods that may help the developers in their applications. I 'll do it :) and i open the space for all to share their own.

I come up with 9 as the first part for this mission and here we 're ...

Using the code

1. Chunck

Which is divide a collection into chunks or parts according to the (n) which is the number of the elements in each part, its code look like this:

VB
<Extension> _
Public Iterator Function Chunk(Of T)(source As IEnumerable(Of T), _
       n As Integer) As IEnumerable(Of IEnumerable(Of T))
    While source.Any()
        Yield source.Take(n)
        source = source.Skip(n)
    End While
End Function

2. Shuffle

Which is shuffle the elements for specific collections randomly, this is useful whenever you want to rearrange the elements, its code look like this:

VB
<Extension> _
Public Function Shuffle(Of T)(source As IEnumerable(Of T)) As IEnumerable(Of T)
        Return source.OrderBy(Function() Guid.NewGuid())
End Function 

3. Randomize

Which is pick up a random element from a specific collection, of course i using the previous function to shuffle them first after that pick an element, its code look like this:

VB
<Extension> _
Public Function Randomize(Of T)(source As IEnumerable(Of T)) As T
    Return source.Shuffle().First()
End Function

4. Merge

Which is merge the elements of specific collection, this useful if you have a list of contacts and you want to send an email to all contacts in one go. This method accept the separator which is by default "", its code look like this:

VB
<Extension> _
Public Function Merge(Of T)(source As IEnumerable(Of T), _
       Optional seperator As String = "") As String
    Return String.Join(seperator, source.ToList())
End Function

5. ToJson

Which is export the elements of specific collection into JSON format, that's very useful whenever you want to export your data, it's open the space to export them into JSON, XML, CVS .. etc, its code look like this:

VB
<Extension> _
Public Function ToJson(Of T)(source As IEnumerable(Of T)) As String
    Dim js As New JavaScriptSerializer()
    Return js.Serialize(source)
End Function

6. With

Which is let you deal with specific property in your collection, for example if we have a collection of Person and we interest with the Address for the people. This method comes for the rescue, it accept a Func delegate to specify the property you 're interest in, after that you can start composition with other LINQ functions , its code look like this:

VB
<Extension> _
Public Function [With](Of T, R)(source As IEnumerable(Of T), _
       target As Func(Of T, R)) As IEnumerable(Of R)
    Return source.Select(target)
End Function

7. Apply

Which is let you apply a certain function to all of the elements with the collection. If you notice LINQ gave us ForEach function, nothing but this function apply an action to the elements, but there 're many scenarios you want to apply a Func instead of Action, so this method comes for the rescue, its code look like this:

VB
<Extension> _
Public Iterator Function Apply(Of T)(source As IEnumerable(Of T), _
       predicate As Func(Of T, T)) As IEnumerable(Of T)
    For Each item In source
        Yield predicate(item)
    Next
End Function

8. RegEx

Which is very useful whenever you want regular expression for some reason, its code look like this:

VB
<Extension> _
Public Iterator Function RegEx(source As IEnumerable(Of String), _
       pattern As String) As IEnumerable(Of String)
    For Each item In source
        Dim rx As New Regex(pattern)
        If rx.IsMatch(item) Then
            Yield item
        End If
    Next
End Function 

9. Dump

Which is dump the entire collection to specific TextWriter, its code look like this:

VB
<Extension> _
Public Sub Dump(Of T)(source As IEnumerable(Of T), writer As TextWriter)
    For Each item As T In source
        If Not item.GetType().ToString().StartsWith("System.") Then
            For Each p In item.GetType().GetProperties(BindingFlags.Instance Or BindingFlags.Public)
                If p.GetValue(item, Nothing).ToString().Contains("+") Then
                     writer.WriteLine("[{0}]", p.Name)
                     DumpTree(p.GetValue(item, Nothing), writer)
                Else
                     writer.WriteLine("{0} : {1}", p.Name, p.GetValue(item, Nothing))
                End If
            Next
        Else
            writer.WriteLine(item)
        End If
            Console.WriteLine()
        Next
End Sub
Private Sub DumpTree(obj As Object, writer As TextWriter, Optional intend As Integer = 0)
    If TypeOf obj Is ICollection Then
        For Each item In obj
            DumpTree(item, writer)
        Next
    Else
        For Each p In obj.GetType().GetProperties(BindingFlags.Instance Or _
                      BindingFlags.NonPublic Or BindingFlags.Public)
            If p.GetValue(obj, Nothing).ToString().Contains("+") Then
                intend += 1
                writer.WriteLine("{0}[{1}]", " ".PadLeft(intend), p.Name)
                DumpTree(p.GetValue(obj, Nothing), writer, intend)
            Else
                writer.WriteLine("{0} {1} : {2}", " ".PadLeft(intend), _
                                 p.Name, p.GetValue(obj, Nothing))
            End If
        Next
    End If
End Sub 

Today I come up with 11 as the second part for this mission and here we 're ...

10. Add

Which is adds set of numbers with specified number, its code look like this:

VB
<Extension()>
Public Function Add(source As IEnumerable(Of Double), number As Integer) As IEnumerable(Of Double)
    Return source.Select(Function(n) n + number)
End Function 

11. Subtract

Which is subtract a specified number from a set of numbers, its code look like this:

VB
<Extension()>
Public Function Subtract(source As IEnumerable(Of Double), number As Integer) As IEnumerable(Of Double)
   Return source.Select(Function(n) n - number)
End Function

11. Multiply

Which is multiply a set of numbers into a specified number, its code look like this:

VB
<Extension()>
Public Function Multiply(source As IEnumerable(Of Double), number As Integer) As IEnumerable(Of Double)
   Return source.Select(Function(n) n * number)
End Function

12. Divide

Which is divide a set of numbers by a specified number, its code look like this:

VB
<Extension()>
Public Function Divide(source As IEnumerable(Of Double), number As Integer) As IEnumerable(Of Double)
   Return source.Select(Function(n) n / number)
End Function

13. Modulus

Which is calculate the the remaining of division for a set of numbers by a specified number, its code look like this:

VB
<Extension()>
Public Function Modulus(source As IEnumerable(Of Double), number As Integer) As IEnumerable(Of Double)
   Return source.Select(Function(n) n Mod number)
End Function

14. Power

Which is calculate the the power for a set of numbers according to the specified number, its code look like this:

VB
<Extension()>
Public Function Power(source As IEnumerable(Of Double), number As Integer) As IEnumerable(Of Double)
   Return source.Select(Function(n) n ^ number)
End Function

15. SquareRoot

Which is calculate the the square root for a set of numbers, its code look like this:

VB
<Extension()>
Public Function SquareRoot(source As IEnumerable(Of Double)) As IEnumerable(Of Double)
    Return source.Select(Function(n) Math.Sqrt(n))
End Function

16. Even

Which is retrieve the even numbers from a set of numbers, its code look like this:

VB
<Extension()>
Public Function Even(source As IEnumerable(Of Integer)) As IEnumerable(Of Integer)
    Return source.Where(Function(n) n Mod 2 = 0)
End Function

17. Odd

Which is retrieve the odd numbers from a set of numbers, its code look like this:

VB
<Extension()>
Public Function Odd(source As IEnumerable(Of Integer)) As IEnumerable(Of Integer)
    Return source.Where(Function(n) n Mod 2 = 1)
End Function

18. GCD

Which is calculate the greatest common divisor for a set of numbers, its code look like this:

VB
<Extension()>
Public Function GDC(source As IEnumerable(Of Integer)) As Integer
    Dim func As Func(Of Integer, Integer, Integer) = Function(a As Integer, b As Integer) If(b = 0, a, func(b, a Mod b))
    Return source.Aggregate(func)
End Function

19. LCM

Which is calculate the least common multiple for a set of numbers, its code look like this:

VB
<Extension()>
Public Function LCM(source As IEnumerable(Of Integer)) As Integer
    Dim func As Func(Of Integer, Integer, Integer) = Function(a As Integer, b As Integer) a * b / GDC(New Integer() {a, b})
    Return source.Aggregate(func)
End Function

Points of Interest

LINQ is cool and it's extensible, which open the space for the developers to add their own functions using Extension Methods which some so sweet :) , after dig into such things we can create a lot of things beyond the imagination. For example you can write down all the LINQ functions without using System.LINQ which is something i was created in the past, I hope you too guys ...

History

  • Part 1: 2/7/2013
Introducing nine set and formatting functions such as Chunk, Shuffle, ToJson ... etc
  • Part 2: 2/5/2014
Introducing eleven mathematics functions such as Add, Subtract, Power, GCD, LCM .. etc

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
SuggestionSome BIG inefficiencies and some that seem pointless... Pin
Matt T Heffron3-Jun-14 7:21
professionalMatt T Heffron3-Jun-14 7:21 
The Shuffle is very expensive computationally calling NewGuid for each element of the IEnumerable sequence. Since the .OrderBy() requires the whole sequence to be loaded (i.e., it cannot perform the ordering in a lazy manner) it would be much faster instead just to capture the values of the sequence into an array, permute the order of the array and return the permuted array as IEnumerable(Of T).
For an efficient way to Shuffle an array, see my: playing cards game (make Random 4 groups of Numbers in Main Group) Solution 3[^]

Your Merge is just String.Join() with a default separator parameter, restructured as an extension method.

Your With method appears to be exactly one of the forms of Select() ... So why not just use Select()?

Likewise, Apply also appears to be exactly the same form of Select()

RegEx could be improved:
VB
<Extension> _
Public Function RegEx(source As IEnumerable(Of String), _
       pattern As String) As IEnumerable(Of String)
    Dim rx As New Regex(pattern)
    Return source.Where(Function(item) rx.IsMatch(item))
End Function


But the worst for performance is Chunk:
I tried writing this extension method awhile ago and came up with exactly the same thing (except in c#).
Thinking about it a couple hours later I realized that there is a massive amount of extra work being done under the covers.
See my article: Considerations on Efficient use of LINQ Extension Methods[^] for the full analysis.
A positive attitude may not solve every problem, but it will annoy enough people to be worth the effort.

GeneralRe: Some BIG inefficiencies and some that seem pointless... Pin
Hisham Abdullah Bin Ateya11-Aug-14 21:08
Hisham Abdullah Bin Ateya11-Aug-14 21:08 
GeneralMy vote of 5 Pin
Member 433704812-Jul-13 1:41
Member 433704812-Jul-13 1:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.