0

What is the fastest/most efficient way to count how many Computer objects in the collection have a MAC address (I.e. Computer.MACAddress <> "")

<Serializable>
Public Class Computer

    Public Property Name As String
    Public Property FQDN As String
    Public Property Path As String
    Public Property GUID As String
    Public Property MACAddress As String
    Public Property IPAddress As Net.IPAddress

End Class

<Serializable>
Public Class ComputerCollection
    Inherits Collection(Of Computer)
End Class

At the moment I'm using LINQ:

Dim macCount = From comp In computers Where comp.MACAddress <> "" Select comp
ssMACDisc.Text = macCount.Count.ToString + " MAC Addresses Discovered"

Thanks in advance

Daniel
  • 1,399
  • 3
  • 16
  • 29

1 Answers1

1

LINQ also uses loops. But you should prefer the most readable way normally.

Dim nonEmptyMacs = From comp In computers
                   Where Not String.IsNullOrEmpty(comp.MACAddress)
Dim countNonEmptyMacs = nonEmptyMacs.Count()

If you need something more efficient you could use a Lookup(Of Tkey, TElement) to count all the null/empty macs. You can initialize a lookup only via ToLookup. If the collection doesn't change often you can persist it in a field that you can access later. Perhaps you also recreate it from the method that adds new computers. You need a custom IEqualityComparer(Of Computer) which treats null and empty macs equal:

Public Class ComputerMacComparer
    Implements IEqualityComparer(Of Computer)

    Public Function Equals1(x As Computer, y As Computer) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Computer).Equals
        If x Is Nothing OrElse y Is Nothing Then
            Return False
        End If
        If String.IsNullOrEmpty(x.MACAddress) AndAlso String.IsNullOrEmpty(y.MACAddress) Then Return True
        Return x.MACAddress = y.MACAddress
    End Function

    Public Function GetHashCode1(obj As Computer) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Computer).GetHashCode
        If String.IsNullOrEmpty(obj.MACAddress) Then Return 0
        Return obj.MACAddress.GetHashCode()
    End Function
End Class

The good thing: you can use this class for many other LINQ methods like GroupBy or Intesect.

I've used this sample data:

Dim computers As New ComputerCollection
computers.Add(New Computer With {.MACAddress = ""})
computers.Add(New Computer With {.MACAddress = nothing})
computers.Add(New Computer With {.MACAddress = "1"})
computers.Add(New Computer With {.MACAddress = "2"})
computers.Add(New Computer With {.MACAddress = "3"})
computers.Add(New Computer With {.MACAddress = Nothing})

As you can see, there are three computers that have either a null- or empty-mac.

You need one examplary "Null"-Computer that you can use later:

Dim nullComp = New Computer With {.MACAddress = Nothing}

Here is the only code that is necessary to create the lookup and to count all computers:

Dim macLookup = computers.ToLookup(Function(comp) comp, New ComputerMacComparer())
Dim countNull = macLookup(nullComp).Count() ' 3

This should be more efficient since a lookup is similar to a Dictionary. It returns an empty sequence if the key is not contained.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Thanks. I get this error with the code you posted. 'Public ReadOnly Property Count As Integer' has no parameters and its return type cannot be indexed. – Daniel Oct 16 '14 at 19:53
  • @Daniel: are you using the code above? Note that i've edited my answer because in VB.NET you cannot use extension methods with the same name as a property(`Collection(Of T)` has a Count property). Therefore i needed to use the query syntax and `Count` in the next line. That's as efficient as method syntax and also more redable ([i hate the ugly `Function` keyword](http://stackoverflow.com/a/9039282/284240)). – Tim Schmelter Oct 16 '14 at 20:03
  • @Daniel: note that i've added another approach using a lookup. – Tim Schmelter Oct 16 '14 at 20:23