So sánh hai ảnh trong lập trình năm 2024

[Lưu ý: class cho hình của bạn fải chắc chắn full width – 100% nhé, như mình đang xài class img-responsive của bootstrap]

Dùng JQuery để init như sau:

  
  $[document].ready[function[] {  
    $["
# splitterContainer"].imageSplitter[];  
  }];  

Kết quả sau khi inited – JS – UI hỗ trợ so sánh 2 tấm hình – Image Splitter View:

3/ Màu mè chút cho cái Splitter Control

Thêm class như sau vào cái container để màu mè chút nè:

  • .is-primary
  • .is-success
  • .is-info
  • .is-warning
  • .is-danger

Kết quả:

[Mặc định là màu hồng đó nha]

4/ Kết luận về JS – UI hỗ trợ so sánh 2 tấm hình – Image Splitter View

Mong rằng với library này nó có thể giúp bạn tiếp cận dc UI này nhanh nhất có thể =]]

Lưu ý cuối khi sử dụng: Các bạn phải đảm bảo 2 tấm hình của bạn nó same nhau như sau:

  • Full-width [100% page-width]
  • Width bằng nhau
  • Height bằng nhau

Không thì tỉ lệ nó break control là cao lắm nhé 😀

Cám ơn các bạn đã quan tâm theo dõi topic này – JS – UI hỗ trợ so sánh 2 tấm hình – Image Splitter View

# JS – UI hỗ trợ so sánh 2 tấm hình – Image Splitter View

Mình là Phát - biệt danh Seth Phát. Hiện đang là một Sr. Full-Stack Engineer. Mình là một người yêu thích và đam mê lập trình và hiện tại đang theo về phần Web là chủ yếu. Mạnh Back-end và khá Front-end, vẫn đang theo đều cả 2 :v. Còn gì bằng khi được làm những thứ mà mình yêu thích, đam mê ;]

Lâu rồi không viết bài về technical nên phải viết 1 bài cho thiên hạ biết mình vẫn code :D. Ở bài viết này, mình sẽ nói về một chuyện khá đơn giản trong C#: So sánh 2 object. Đây là một vấn đề ai cũng tưởng là dễ, mình sẽ nâng dần vấn đề lên từ đơn giản đến phức tạp. Cách giải quyết cũng sẽ từ đơn giản trở nên phức tạp, sau đó sẽ trở lại đơn giản. Nếu chịu khó đọc bài viết này từ đầu đến cuối, các bạn sẽ ngộ ra nhiều điều, khả năng technical cũng sẽ tăng kha khá đấy.

Cấp độ 1: Class đơn giản

Chúng ta bắt đầu bài toán với một class đơn giản nhé. Class này có 3 properties, khi ta gọi hàm Equals, C# chỉ so sánh reference, do đó kết quả là False

public class Student { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } } var student1 = new Student { FirstName = "Pham", LastName = "Hoang", Age = 15, }; var student2 = new Student { FirstName = "Pham", LastName = "Hoang", Age = 15, }; student1.Equals[student2]; //False

Để xử lý chuyện này, chúng ta chỉ cần override lại hàm Equals là xong, không phức tạp, chắc bạn nào cũng đã học ở trường nhỉ

public override bool Equals[object obj] { if [obj == null || GetType[] != obj.GetType[]] return false; var student = [Student] obj; return FirstName.Equals[student.FirstName]

     && LastName.Equals[student.LastName]  
     && Age == student.Age  
     && BirthDate.Equals[student.BirthDate];  
}

Cấp độ 2: Sử dụng extension method

Hàm Equals vẫn còn khuyết điểm, đó là student1 không được null. Ta có thể xử lý vấn đề này bằng cách sử dụng extension method như sau. Giờ ta có thể gọi student1.Equals[student2] dù student1 có null đi nữa:

public static bool DeepEquals[this Student obj, Student another] { //Nếu null hoặc giống nhau, trả true if [ReferenceEquals[obj, another]] return true; //Nếu 1 trong 2 là null, trả false if [[obj == null] || [another == null]] return false; return obj.FirstName.Equals[another.FirstName]

    && obj.LastName.Equals[another.LastName]  
    && obj.Age == another.Age  
    && obj.BirthDate.Equals[another.BirthDate];  
}

Cấp độ 3: Viết method để so sánh 2 object nói chung

Hãy nghĩ tới trường hợp ứng dụng của bạn có khoảng vài chục class, mỗi class có vài chục property. Bạn sẽ làm gì? Hì hục viết tay hàm Equals cho từng class? Hãy sử dụng Refection trong C# để viết 1 hàm so sánh object có thể dùng cho mọi object.

public static bool DeepEquals[this object obj, object another] { if [ReferenceEquals[obj, another]] return true; if [[obj == null] || [another == null]] return false; //So sánh class của 2 object, nếu khác nhau thì trả fail if [obj.GetType[] != another.GetType[]] return false; var result = true; //Lấy toàn bộ các properties của obj //sau đó so sánh giá trị của từng property foreach [var property in obj.GetType[].GetProperties[]] {

  var objValue = property.GetValue[obj];  
  var anotherValue = property.GetValue[another];  
  if [!objValue.Equals[anotherValue]] result = false;  
} return result; } Hàm này chạy khá OK. Bạn đang tự hỏi: Ối dào, dễ thế này mà cũng viết? Chưa đâu, hãy xem tiếp phía dưới, nhiều thứ “đáng sợ” hơn đang chờ đấy.

Cấp độ 4: Trường hợp object chứa object hoặc struct như DateTime

Ở cấp độ trên, ta viết hàm so sánh từng trường. Thế nhưng giả sử trong class Student, ta có chứa DateTime hoặc 1 class khác thì sao nhỉ??

public class Student { public string FirstName { get; set; } public string LastName { get; set; } public DateTime BirthDate { get; set; } public Teacher Teacher { get; set; } } public class Teacher { public string Name { get; set; } public string Subject { get; set; } } var student1 = new Student { FirstName = "Pham", LastName = "Hoang", BirthDate = new DateTime[1992, 12, 5], Teacher = new Teacher { Name = "Le Minh", Subject = "Math"} }; var student2 = new Student { FirstName = "Pham", LastName = "Hoang", BirthDate = new DateTime[1992, 12, 5], Teacher = new Teacher { Name = "Le Minh", Subject = "Math" } };

Suy nghĩ 1 tí nào. Để giải quyết, ta cũng sẽ so sánh từng trường, nhưng nếu trường đó là một object thì ta sẽ so sánh bằng hàm DeepEquals đã viết. Một thuật giải đệ quy cơ bản thôi mà 😀

public static bool DeepEquals[this object obj, object another] { if [ReferenceEquals[obj, another]] return true; if [[obj == null] || [another == null]] return false; if [obj.GetType[] != another.GetType[]] return false; //Nếu property không phải class, chỉ là int, double, DateTime v...v //Gọi hàm equal thông thường if [!obj.GetType[].IsClass] return obj.Equals[another]; var result = true; foreach [var property in obj.GetType[].GetProperties[]] {

var objValue = property.GetValue[obj];  
var anotherValue = property.GetValue[another];  
//Tiếp tục đệ quy  
if [!objValue.DeepEquals[anotherValue]]   result = false;  
} return result; }

Wow, thế là đã xong, mọi vấn đề đã được giải quyết, bạn đang tự khen mình giỏi. Ồ, thế còn trường hợp không phải một object, mà là một List thì sao nhỉ, căng đây 😦

Cấp độ 5: So sánh 2 list

May thay, ta có thể viết extension method cho list như sau [Chữ là generic nhé, các bạn có thể đọc bài này để xem lại].

public static bool DeepEquals[this IEnumerable obj, IEnumerable another] { if [ReferenceEquals[obj, another]] return true; if [[obj == null] || [another == null]] return false; bool result = true; //Duyệt từng phần tử trong 2 list đưa vào using [IEnumerator enumerator1 = obj.GetEnumerator[]] using [IEnumerator enumerator2 = another.GetEnumerator[]] { while [true] {

 bool hasNext1 = enumerator1.MoveNext[];  
 bool hasNext2 = enumerator2.MoveNext[];
 //Nếu có 1 list hết, hoặc 2 phần tử khác nhau, thoát khoải vòng lặp  
 if [hasNext1 != hasNext2 || !enumerator1.Current.DeepEquals[enumerator2.Current]]  
 {  
    result = false;  
    break;  
 }
  //Dừng vòng lặp khi 2 list đều hết  
  if [!hasNext1] break;  
} } return result; }

Phù, tạm xong. Chắc không còn gì nữa đâu nhỉ?

var list1 = new List { student1, student2 }; var list2 = new List { student1, student2}; list1 == list2; //True

Cấp độ 6: Một đống những thứ tả pín lù khác

Bạn chợt nhớ ra rằng, trong C# còn hằng hà sa số những thứ tương tự List như Dictionary, HashSet,… chẳng lẽ phải viết hết. Còn một vài trường hợp tréo ngoe hơn, vd như class Student sẽ chứa 1 list cái Teacher, method chúng ta viết không chạy được

var teacherA = new Teacher { Name = "Le Minh", Subject = "Math"}; var teacherB = new Teacher { Name = "Tai Phu", Subject = "Physics"}; var student1 = new Student { FirstName = "Pham", LastName = "Hoang", Age = 15, BirthDate = new DateTime[1992, 12, 5], Teacher = new List { teacherA, teacherB} }; var student2 = new Student { FirstName = "Pham", LastName = "Hoang", Age = 15, BirthDate = new DateTime[1992, 12, 5], Teacher = new List { teacherA, teacherB} };

Tới đây mình cũng bó tay rồi, con đường phía trước khá rắc rối gian nan và phức tạp :'[. Bạn được chọn 1 trong 2 lựa chọn sau:

  1. Với những class khó quá, hãy tự viết hàm Equals, cũng không nhiều lắm
  2. Theo đuổi hàm generic tới cùng, bằng cách đọc tiếp bài này.

Cấp độ cuối cùng: Cầu cứu anh JSON

Cách giải quyết vấn đề thật ra đơn giản hơn bạn nghĩ. Hãy serialize 2 object đó dưới dạng chuỗi JSON, so sánh 2 chuỗi được tạo ra là xong. [Việc serialize ra json đã giải quyết 99% vấn đề phức tạp liên quan đến các kiểu dữ liệu rồi, may quá :D].

Các bước thực hiện:

1. Add Reference Newtonsoft.JSON theo hướng dẫn, được kết quả như hình 3 là ok.

2. Viết 1 hàm so sánh gọn nhẹ đơn giản:

public static bool JSONEquals[this object obj, object another] { if [ReferenceEquals[obj, another]] return true; if [[obj == null] || [another == null]] return false; if [obj.GetType[] != another.GetType[]] return false; var objJson = JsonConvert.SerializeObject[obj]; var anotherJson = JsonConvert.SerializeObject[another]; return objJson == anotherJson; }

Có 1 vài thư viện khác, các bạn có thể search trên google với từ khóa: Deep Compare C#.

Vì bài viết khá dài, lại hơi thiên về technical nên mình đã cố gắng khiến nó hấp dẫn hơn. Chúc mừng các bạn nếu các bạn chịu khó đọc được đến cuối cùng. Phần thưởng cho các bạn kiên nhẫn đây: 5 bạn comment đầu tiên trong bài viết này có quyền request mình viết 1 bài về 1 khía cạnh trong C#, MVC hoặc javascript mà bạn muốn tìm hiểu nhé. Chúc các bạn may mắn.

Chủ Đề