کار با HashSet در#C

پنجشنبه 14 مرداد 1395

در این مقاله HashSet به‌عنوان یک کالکشن -المان- تکراری ناپذیر معرفی شده و برخی از متدهای مهم آن همراه با مثال معرفی می‌گردند.

کار با HashSet در#C

HashSet یک کالکشن (collection) نامرتب از المان‌های منحصربه‌فرد و غیرتکراری است که در .NET 3.5 معرفی شد و داخل namespace System.Collection.Generic قرار دارد و کاربرد آن زمانیست که بخواهید از تکراری‌شدن نمونه‌های واردشده به کالکشن جلوگیری کنید. در مواردی که کارایی مدنظر باشد، این کالکشن از لیست (List) مناسب‌تر است. در این مقاله کار را با ساختن یک HashSet ساده شروع می‌کنیم که در ادامه کارهای مختلفی روی HashSet انجام می‌گیرد. در پایانِ این مقاله به شما نشان خواهم داد که چگونه یک HashSet را از نوع‌های مختلفی بسازیم و از تکراری‌شدن ورودی‌های آن جلوگیری به‌عمل آوریم.اجازه بدید کار را با یه مثال شروع کنیم:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
namespace HashSetDemo {  
    class Program {  
        static void Main(string[] args) {  
            HashSet < string > names = new HashSet < string > {  
                "Rajeev",  
                "Akash",  
                "Amit"  
            };  
            foreach(var name in names) {  
                Console.WriteLine(name);  
            }  
            Console.ReadKey();  
        }  
    }  
}  

نتیجه‌ی برنامه

 در کد بالا، ما یک HashSet ساده را از نوع رشته‌ای (string) پدید آورده و رشته‌ها را به‌آن اضافه می‌کنیم. درعین حال می‌توانیم رشته‌ها را توسط متد add اضافه کنیم. در قطعه‌ای که پایین آمده، نحوه استفاده از متد add را ملاحظه می‌کنیم. ما الان سعی می‌کنیم رشته‌های تکراری‌ای را اضافه کنیم و ببینیم چه اتفاقی می‌افتد.

using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
namespace HashSetDemo {  
    class Program {  
        static void Main(string[] args) {  
            HashSet < string > names = new HashSet < string > {  
                "Rajeev",  
                "Akash",  
                "Amit"  
            };  
            names.Add("Rajeev");  
            //duplicates are not added into collection.   
            foreach(var name in names) {  
                Console.WriteLine(name);  
            }  
            Console.ReadKey();  
        }  
    }  
}  

نتیجه‌ی برنامه

در قطعه‌کد آمده در بالا با اینکه ما سعی کردیم رشته‌های تکراری را وارد کنیم، اما با هیچ خطایی مواجه نشدیم ولی وقتی کالکشن را تکرار کنیم، دیگه نمی‌توانیم رشته را پیدا کنیم. این نشان‌دهنده‌ی این است که ما نمی‌توانیم المان‌های تکراری را به HashSet اضافه کنیم. الان دیگه وقت آن رسیده که به بعضی از متدهای مهم HashSet نگاهی بیاندازیم.

UnionWith

این متد المان‌هایی را که در هردو کالکش قرار دارند، در کالکشن مورد فراخوانی ترکیب می‌کند.

using System;

using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
namespace HashSetDemo {  
    class Program {  
        static void Main(string[] args) {  
            HashSet < string > names = new HashSet < string > {  
                "Rajeev",  
                "Akash",  
                "Amit"  
            };  
            HashSet < string > names1 = new HashSet < string > {  
                "Rajeev",  
                "Akash",  
                "Amit",  
                "Deepak",  
                "Mohit"  
            };  
            names.UnionWith(names1);  
            foreach(var name in names) {  
                Console.WriteLine(name);  
            }  
            Console.ReadKey();  
        }  
    }  
}  

نتیجه‌ی برنامه

IntersectWith

این متد المان‌هایی را که بین دو کالکشن مشترک هستند باهم ترکیب می‌کند.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
namespace HashSetDemo {  
    class Program {  
        static void Main(string[] args) {  
            HashSet < string > names = new HashSet < string > {  
                "Rajeev",  
                "Akash",  
                "Amit"  
            };  
            HashSet < string > names1 = new HashSet < string > {  
                "Rajeev",  
                "Akash",  
                "Amit",  
                "Deepak",  
                "Mohit"  
            };  
            names.IntersectWith(names1);  
            foreach(var name in names) {  
                Console.WriteLine(name);  
            }  
            Console.ReadKey();  
        }  
    }  
}  

نتیجه‌ی برنامه

ExceptWith

این متد تمامی المان‌های کالکشن دیگر را از کالکشن موردفراخوانی حذف می‌کند.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
namespace HashSetDemo {  
    class Program {  
        static void Main(string[] args) {  
            HashSet < string > names = new HashSet < string > {  
                "Rajeev",  
                "Akash",  
                "Amit"  
            };  
            HashSet < string > names1 = new HashSet < string > {  
                "Rajeev",  
                "Akash",  
                "Amit",  
                "Deepak",  
                "Mohit"  
            };  
            names1.ExceptWith(names);  
            foreach(var name in names1) {  
                Console.WriteLine(name);  
            }  
            Console.ReadKey();  
        }  
    }  
}  

نتیجه‌ی برنامه

اکنون اجازه دهید یک مرحله جلوتر برویم، کلاسی را ساخته و سعی کنیم یک HashSet از نوع کلاس ایجاد کرده و تلاش نماییم المان‌هایی تکراری را به‌آن اضافه کنیم.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
namespace HashSetDemo {  
    class Program {  
        static void Main(string[] args) {  
            Console.WriteLine("-----Custom HashSet With Duplicates----");  
            HashSet < Employee > employees = new HashSet < Employee > {  
                {  
                    new Employee {  
                        Emp_Id = 1, Emp_name = "Rajeev", Dept_name = "IT"  
                    }  
                },  
                {  
                    new Employee {  
                        Emp_Id = 1, Emp_name = "Rajeev", Dept_name = "IT"  
                    }  
                },  
                {  
                    new Employee {  
                        Emp_Id = 3, Emp_name = "Akash", Dept_name = "IT"  
                    }  
                },  
                {  
                    new Employee {  
                        Emp_Id = 4, Emp_name = "Amit", Dept_name = "IT"  
                    }  
                }  
            };  
            Console.WriteLine("{0,-6}{1,10}{2,-8}", "Emp_Id", "Emp_name", "Dept_name");  
            Console.WriteLine("==============================");  
            foreach(var employee in employees) {  
                Console.WriteLine("{0,-8}{1,-10}{2,5}", employee.Emp_Id, employee.Emp_name, employee.Dept_name);  
            }  
            Console.WriteLine("==============================");  
            Console.ReadKey();  
        }  
    }  
    public class Employee {  
        public int Emp_Id {  
            get;  
            set;  
        }  
        public string Emp_name {  
            get;  
            set;  
        }  
        public string Dept_name {  
            get;  
            set;  
        }  
    }  
}  

نتیجه‌ی برنامه

ما درمی‌یابیم که HashSet در کالکشن اجازه‌ی تکرار را نمی‌دهد لیکن همچنان در خروجی‌ رکوردهای تکراری داریم. به‌منظور غلبه بر این مشکل نیازمند پیاده‌سازی رابط (interface) IEquatable، حذف موارد مساوی، ومتد GetHashCode می‌باشیم.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
namespace HashSetDemo {  
    class Program {  
        static void Main(string[] args) {  
            Console.WriteLine("-----Custom HashSet With Duplicates----");  
            HashSet < Employee > employees = new HashSet < Employee > {  
                {  
                    new Employee {  
                        Emp_Id = 1, Emp_name = "Rajeev", Dept_name = "IT"  
                    }  
                },  
                {  
                    new Employee {  
                        Emp_Id = 1, Emp_name = "Rajeev", Dept_name = "IT"  
                    }  
                },  
                {  
                    new Employee {  
                        Emp_Id = 3, Emp_name = "Akash", Dept_name = "IT"  
                    }  
                },  
                {  
                    new Employee {  
                        Emp_Id = 4, Emp_name = "Amit", Dept_name = "IT"  
                    }  
                }  
            };  
            Console.WriteLine("{0,-6}{1,10}{2,-8}", "Emp_Id", "Emp_name", "Dept_name");  
            Console.WriteLine("==============================");  
            foreach(var employee in employees) {  
                Console.WriteLine("{0,-8}{1,-10}{2,5}", employee.Emp_Id, employee.Emp_name, employee.Dept_name);  
            }  
            Console.WriteLine("==============================");  
            Console.ReadKey();  
        }  
    }  
    public class Employee: IEquatable < Employee > {  
        public int Emp_Id {  
            get;  
            set;  
        }  
        public string Emp_name {  
            get;  
            set;  
        }  
        public string Dept_name {  
            get;  
            set;  
        }  
        public bool Equals(Employee other) {  
            return this.Emp_Id.Equals(other.Emp_Id);  
        }  
        public override int GetHashCode() {  
            return this.Emp_Id.GetHashCode();  
        }  
    }  
}  

نتیجه‌ی برنامه

بنابراین HashSet یک کالکشن عمومیست (generic) که اجازه‌ی تکرار را نمی‌دهد. ما می‌توانیم برای حذف تکراری‌های هر کالکشنی مانند List از HashSet استفاده کنیم.

using System;
using System.Collections.Generic;
 namespace HashSetDemo
{
public class Program
{
	public static void Main()
	{
		HashSet<string> names=new HashSet<string>{"Rajeev", "Akash", "Amit"};
		foreach(var country in names)
		{
		Console.WriteLine(country);
		}
		names.Add("Rajeev");
		Console.WriteLine("---------");
		//duplicates are not added into collection.
		foreach(var name in names)
		{
		Console.WriteLine(name);
		}
		
		//ExceptWith 
		
		HashSet<string> names1=new HashSet<string>{"Rajeev", "Akash", "Amit","Deepak","Mohit"};
		
		names1.ExceptWith(names);
		Console.WriteLine("-----ExceptWith(elements not present in second(names)----");
		foreach(var name in names1)
		{
		Console.WriteLine(name);
		}
		
		//IntersectWith 
		
		names.IntersectWith(names1);
		Console.WriteLine("-----IntersectWith(elements common----");
		foreach(var name in names1)
		{
		Console.WriteLine(name);
		}
		
		
		
		//UnionWith
		
				
		names.UnionWith(names1);
		Console.WriteLine("-----UnionWith----");
		foreach(var name in names)
		{
		Console.WriteLine(name);
		}
		
		Console.WriteLine("-----Custom HashSet With Duplicates----");
		HashSet<Employee> employees=new HashSet<Employee>
		{
			{new Employee{Emp_Id=1,Emp_name="Rajeev",Dept_name="IT"}},
			{new Employee{Emp_Id=1,Emp_name="Rajeev",Dept_name="IT"}},
			{new Employee{Emp_Id=3,Emp_name="Akash",Dept_name="IT"}},
			{new Employee{Emp_Id=4,Emp_name="Amit",Dept_name="IT"}}
		};
		Console.WriteLine("{0,-6}{1,10}{2,-8}","Emp_Id","Emp_name","Dept_name");
		Console.WriteLine("==============================");
		foreach(var employee in employees)
		{
			Console.WriteLine("{0,-8}{1,-10}{2,5}",employee.Emp_Id,employee.Emp_name,employee.Dept_name);
		}
		Console.WriteLine("==============================");
	}
}
	 //Implement IEquatable Interface methods Equals and GetHashCode
	 public class Employee:IEquatable<Employee>
	{
		 public int Emp_Id{get;set;}
		 public string Emp_name{get;set;}
		 public string Dept_name{get;set;}
		 public bool Equals(Employee other)
        {
			
                return this.Emp_Id.Equals(other.Emp_Id);
			
        }

        public override int GetHashCode()
        {
                return this.Emp_Id.GetHashCode();
        }
	 }
}

آموزش سی شارپ

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان
  • C#.net
  • 2k بازدید
  • 5 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید