Since the time I “finished” this series of articles on Lambda Expressions, there were a couple of more questions asked on the Forums that lent themselves well to using a Lambda Expression. I thought I would discuss those here to provide some more ideas on the use of LEs. I’ve also included a solution using a LINQ query, since they go hand-in-hand.
The first post was “getting the most recently modified file in a folder with wildcards (e.g. file *.txt)”.
Like many things in .NET, there are usually many ways to get what you want. In this case, first you have to decide what to use to retrieve all the files from a folder with a particular extension. The DirectoryInfo Class has a nice overloaded method named GetFiles. This allows you to specify a search pattern, as well as search option specifying to search the top-directory only or all directories. This is different than the System.IO Directory Class, which also has a GetFiles method, allowing you to also specify a search pattern and search option. The difference is the Directory GetFiles method returns an array of the File names. The DirectoryInfo Class GetFiles method returns an array of FileInfo objects.
Before we go any further let’s set up our Form. Add 2 Buttons and 3 ListBoxes. Since the GetFiles method returns an array, we’ll need a collection to hold them. Except in rare cases I use a List(Of T). In the Button1 Click event declare a List(Of FileInfo), and also declare a DirectoryInfo object, using the path to a folder containg a number of different file types. Then fill the List using the GetFiles method, using .txt as the search pattern and TopDirectoryOnly for the search option. Once the List is populated, we’ll iterate through it and add the file name and last write time to ListBox1.
<code>
Dim lstFiles As New List(Of FileInfo)
Dim dInfo As New DirectoryInfo("C:\Users\Joe\Desktop\Test Folder")
lstFiles = dInfo.GetFiles("*.txt", SearchOption.TopDirectoryOnly).ToList
For Each fi As FileInfo In lstFiles
ListBox1.Items.Add(fi.Name & " " & fi.LastWriteTime.ToShortDateString)
Next
</code>
Since I have the files in the folder sorted by name, the items should be added in alphabetical order by file name. Next we’ll use the Sort method of the List(Of T), performing the sort with a Lambda Expression. Now that the List is sorted, we can iterate through it again, adding the file name and last write time to ListBox2. Now the files should be listed in ascending order by last write time. Add this to the Button1 Click event:
<code>
lstFiles.Sort(Function(a, b) Date.Compare(a.LastWriteTime, b.LastWriteTime))
Debug.WriteLine(String.Format("{0} was last modified on {1}", lstFiles(0).Name, lstFiles(0).LastWriteTime)) 'oldest file
Debug.WriteLine(String.Format("{0} was last modified on {1}", lstFiles(lstFiles.Count - 1).Name, lstFiles(lstFiles.Count - 1).LastWriteTime)) 'newest file
For Each fi As FileInfo In lstFiles
ListBox2.Items.Add(fi.Name & " " & fi.LastWriteTime.ToShortDateString)
Next
</code>
Note that if you want to sort in descending order, you can reverse the FileInfo parameters within the Lambda Expression:
<code> lstFiles.Sort(Function(a, b) Date.Compare(b.LastWriteTime, a.LastWriteTime)) </code>
In the Button2 Click event, we’ll use a LINQ query with an Order By clause, specifying Descending. Then iterate through the List again, adding the items to ListBox3.
<code>
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim lstFiles As New List(Of FileInfo)
Dim dInfo As New DirectoryInfo("C:\Users\Joe\Desktop\Test Folder")
lstFiles = dInfo.GetFiles("*.txt").ToList
Dim query = From fn In lstFiles.AsEnumerable Order By fn.LastWriteTime Descending
Debug.WriteLine(String.Format("{0} was last modified on {1}", query(0).Name, query(0).LastWriteTime)) 'newest file
Debug.WriteLine(String.Format("{0} was last modified on {1}", query(query.Count - 1).Name, query(query.Count - 1).LastWriteTime)) 'oldest file
For Each fi As FileInfo In query
ListBox3.Items.Add(fi.Name & " " & fi.LastWriteTime.ToShortDateString)
Next
End Sub
</code>
The second Forum post was a question about getting a count of each item in an Excel column. The OP has an Excel sheet containing a list of students and their ages, and wants to get the count of students at each age: x number of 5 year olds, y number of 6 year olds, etc. Sounded like a fun question to work on!
Unfortunately this was a question about VBA, and I don’t know if VBA supports Lambda Expressions (or even LINQ). However, I still decided to solve the question using .NET. Create an app with 2 Buttons, 2 ListBoxes and a DataGridView on the Form. We’ll instantiate a DataTable to hold the data (simulating the Excel sheet) and display it in the DataGridView.
<code>
Dim dtTest As New DataTable
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
dtTest.Columns.Add("F_Name", GetType(String))
dtTest.Columns.Add("G_Class", GetType(String))
dtTest.Columns.Add("Age", GetType(Integer))
Dim rndm As New Random
For i As Integer = 1 To 10
dtTest.Rows.Add(Chr(rndm.Next(65, 91)), Chr(rndm.Next(97, 102)), rndm.Next(5, 16))
Next
DataGridView1.DataSource = dtTest.DefaultView
End Sub
</code>
We’ll start with the LINQ query in the Button1 Click event.
<code>
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For i As Integer = 5 To 15
Dim int As Integer = i
Dim cnt As Integer = (From n In dtTest.AsEnumerable Where n.Field(Of Integer)("Age") = int Select n).Count
If Not cnt = 0 Then
ListBox1.Items.Add((String.Format("There are {0} children aged {1} years", cnt.ToString, int.ToString)))
End If
Next
End Sub
</code>
And the corresponding LE:
<code>
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
For i As Integer = 5 To 15
Dim int As Integer = i
Dim cnt = dtTest.AsEnumerable.Count(Function(a) a.Field(Of Integer)("Age") = int)
If Not cnt = 0 Then
ListBox2.Items.Add((String.Format("There are {0} children aged {1} years", cnt.ToString, int.ToString)))
End If
Next
End Sub
</code>
A couple of more examples of the ability of LINQ and LEs to perform different tasks in .NET.





![Desire.. [Explored] 22.2.12 Desire.. [Explored] 22.2.12](http://static.flickr.com/7194/6921502699_4cb090c84f_t.jpg)



