locked
Want a challenge III RRS feed

  • Question

  • This one is open game

    Note going in, not looking for preventing a duplication from being entered, the scenario is you have this coming in from another source. 

    Given the following class

    Public Class Product
        Public Property ProductName() As String
        Public Property CategoryIdentifier() As Integer
    End Class

    With this list

    Dim products = New List(Of Product) From {
        New Product() With {.CategoryIdentifier = 5, .ProductName = "Apples"},
        New Product() With {.CategoryIdentifier = 7, .ProductName = "Apples"},
        New Product() With {.CategoryIdentifier = 5, .ProductName = "Apples"},
        New Product() With {.CategoryIdentifier = 1, .ProductName = "Grapes"},
        New Product() With {.CategoryIdentifier = 11, .ProductName = "Bread"}
    }

    Implement IEquatable to the Product class for removing duplicates on a combination of both properties from the list above.

    Final code

    Dim products = New List(Of Product) From {
        New Product() With {.CategoryIdentifier = 5, .ProductName = "Apples"},
        New Product() With {.CategoryIdentifier = 7, .ProductName = "Apples"},
        New Product() With {.CategoryIdentifier = 5, .ProductName = "Apples"},
        New Product() With {.CategoryIdentifier = 1, .ProductName = "Grapes"},
        New Product() With {.CategoryIdentifier = 11, .ProductName = "Bread"}
    }
    Dim noDuplicates = products.Distinct()
    
    For Each product As Product In noDuplicates
        Console.WriteLine($"{product.CategoryIdentifier}, {product.ProductName}")
    Next

    Results

    5, Apples
    7, Apples
    1, Grapes
    11, Bread

    All working code will be marked as an answer.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange


    Saturday, October 19, 2019 9:36 PM
    Moderator

Answers

  • This is beyond what I am familiar with but I think this works. The following code was converted from C# code so I am doing the Main a bit differently.The hash code might not be ideal, it is a challenge to know what is a good hash code.

    Public Class Product
    	Implements IEquatable(Of Product)
    
    	Public Property ProductName() As String
    	Public Property CategoryIdentifier() As Integer
    
    	Public Overrides Function GetHashCode() As Integer
    		Return Me.ProductName.GetHashCode() + CategoryIdentifier
    	End Function
    
    	Public Overrides Function Equals(ByVal obj As Object) As Boolean
    		If Not (TypeOf obj Is Product) Then
    			Return False
    		End If
    		Return Equals(DirectCast(obj, Product))
    	End Function
    
        Public Overloads Function Equals(ByVal other As Product) As Boolean Implements IEquatable(Of Product).Equals
            If ProductName <> other.ProductName Then
                Return False
            End If
            Return CategoryIdentifier = other.CategoryIdentifier
        End Function
    
        Public Shared Operator =(ByVal product1 As Product, ByVal product2 As Product) As Boolean
    		Return product1.Equals(product2)
    	End Operator
    
    	Public Shared Operator <>(ByVal product1 As Product, ByVal product2 As Product) As Boolean
    		Return Not product1.Equals(product2)
    	End Operator
    End Class
    
    Friend Class Program
    
    	Shared Sub Main(ByVal args() As String)
    		Dim products As New List(Of Product)() From {
    			New Product() With {
    				.CategoryIdentifier = 5,
    				.ProductName = "Apples"
    			},
    			New Product() With {
    				.CategoryIdentifier = 7,
    				.ProductName = "Apples"
    			},
    			New Product() With {
    				.CategoryIdentifier = 5,
    				.ProductName = "Apples"
    			},
    			New Product() With {
    				.CategoryIdentifier = 1,
    				.ProductName = "Grapes"
    			},
    			New Product() With {
    				.CategoryIdentifier = 11,
    				.ProductName = "Bread"
    			}
    		}
    
    		Dim noDuplicates As IEnumerable(Of Product) = products.Distinct()
    		For Each product As Product In noDuplicates
    			Console.WriteLine($"{product.CategoryIdentifier}, {product.ProductName}")
    		Next product
    	End Sub
    End Class
    



    Sam Hobbs
    SimpleSamples.Info

    Sunday, October 20, 2019 7:39 PM

All replies

  • This is beyond what I am familiar with but I think this works. The following code was converted from C# code so I am doing the Main a bit differently.The hash code might not be ideal, it is a challenge to know what is a good hash code.

    Public Class Product
    	Implements IEquatable(Of Product)
    
    	Public Property ProductName() As String
    	Public Property CategoryIdentifier() As Integer
    
    	Public Overrides Function GetHashCode() As Integer
    		Return Me.ProductName.GetHashCode() + CategoryIdentifier
    	End Function
    
    	Public Overrides Function Equals(ByVal obj As Object) As Boolean
    		If Not (TypeOf obj Is Product) Then
    			Return False
    		End If
    		Return Equals(DirectCast(obj, Product))
    	End Function
    
        Public Overloads Function Equals(ByVal other As Product) As Boolean Implements IEquatable(Of Product).Equals
            If ProductName <> other.ProductName Then
                Return False
            End If
            Return CategoryIdentifier = other.CategoryIdentifier
        End Function
    
        Public Shared Operator =(ByVal product1 As Product, ByVal product2 As Product) As Boolean
    		Return product1.Equals(product2)
    	End Operator
    
    	Public Shared Operator <>(ByVal product1 As Product, ByVal product2 As Product) As Boolean
    		Return Not product1.Equals(product2)
    	End Operator
    End Class
    
    Friend Class Program
    
    	Shared Sub Main(ByVal args() As String)
    		Dim products As New List(Of Product)() From {
    			New Product() With {
    				.CategoryIdentifier = 5,
    				.ProductName = "Apples"
    			},
    			New Product() With {
    				.CategoryIdentifier = 7,
    				.ProductName = "Apples"
    			},
    			New Product() With {
    				.CategoryIdentifier = 5,
    				.ProductName = "Apples"
    			},
    			New Product() With {
    				.CategoryIdentifier = 1,
    				.ProductName = "Grapes"
    			},
    			New Product() With {
    				.CategoryIdentifier = 11,
    				.ProductName = "Bread"
    			}
    		}
    
    		Dim noDuplicates As IEnumerable(Of Product) = products.Distinct()
    		For Each product As Product In noDuplicates
    			Console.WriteLine($"{product.CategoryIdentifier}, {product.ProductName}")
    		Next product
    	End Sub
    End Class
    



    Sam Hobbs
    SimpleSamples.Info

    Sunday, October 20, 2019 7:39 PM
  • Hi Sam,

    Most who frequent here more likely than not are not familiar with IEquatable Interface. I've used it quite often when cleaning up messes from other developers. I tend not to override equality operators but that is a personal choice when dealing with class instances.

    Anyways thanks for giving this a shot.

    Here is mine version

    Namespace Classes
        Public Class Product
            Implements IEquatable(Of Product)
    
            Public Property ProductName() As String
            Public Property CategoryIdentifier() As Integer
    
            Public Function Equals(other As Product) As Boolean _
                Implements IEquatable(Of Product).Equals
    
                If ReferenceEquals(other, Nothing) Then
                    Return False
                End If
    
                If ReferenceEquals(Me, other) Then
                    Return True
                End If
    
                'Check whether the products' properties are equal. 
                Return CategoryIdentifier.Equals(other.CategoryIdentifier) AndAlso
                       ProductName.Equals(other.ProductName)
    
            End Function
            Public Overrides Function GetHashCode() As Integer
    
                'Get hash code for the Name field if it is not null. 
                Dim hashProductName As Integer = If(ProductName Is Nothing, 0, ProductName.GetHashCode())
    
                'Get hash code for the Code field. 
                Dim hashProductCode As Integer = CategoryIdentifier.GetHashCode()
    
                'Calculate the hash code for the product. 
                Return hashProductName Xor hashProductCode
            End Function
        End Class
    End Namespace
    

    C# version

    using System;
    namespace Operations.Classes
    {
        public class Product : IEquatable<Product>
        {
            public string ProductName { get; set; }
            public int CategoryIdentifier { get; set; }
    
            public bool Equals(Product other)
            {
    
                if (ReferenceEquals(other, null))
                {
                    return false;
                }
    
                if (ReferenceEquals(this, other))
                {
                    return true;
                }
    
                //Check whether the products' properties are equal. 
                return CategoryIdentifier.Equals(other.CategoryIdentifier) && 
                       ProductName.Equals(other.ProductName);
            }
            public override int GetHashCode()
            {
    
                //Get hash code for the Name field if it is not null. 
                var hashProductName = ProductName == null ? 0 : ProductName.GetHashCode();
    
                //Get hash code for the Code field. 
                var hashProductCode = CategoryIdentifier.GetHashCode();
    
                //Calculate the hash code for the product. 
                return hashProductName ^ hashProductCode;
            }
        }
    }
    


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Sunday, October 20, 2019 10:44 PM
    Moderator