
.net’in içerisinde gelen sıralama algoritması maalesef sıralanacak kelimelerin uzunluğunu kontrol etmeden doğrudan alfabetik sıralama yapıyor. Bu da harf ve sayı karışık olan metinleri sıralarken yanlış sıralamaya neden oluyor. Bu yaklaşımın önüne geçmek için Natural Comparer adında bir sınıf kullanacağız.
Örneğin veritabanımızda bir dokuman listemiz olsun:
doküman1 doküman10 doküman3 doküman11 doküman9 doküman11
Bu listeyi .OrderBy(t=>t.dokumankodu) diyerek sıraladığımızda:
doküman1 doküman10 doküman11 doküman3 doküman9
Şeklinde sıralayacaktır. Bu aslında beklenen bir davranış çünkü n harfinden sonra gelen sayılar 1-1-1-3-9 şeklinde. Bunu düzeltmek için şu sınıfı kullanıyoruz:
using System; using System.Collections.Generic; using System.Globalization; using System.Collections; using System.Text.RegularExpressions; namespace TestProject { public class NaturalSortComparer : IComparer, IDisposable { private bool isAscending; public NaturalSortComparer(bool inAscendingOrder = true) { this.isAscending = inAscendingOrder; } public int Compare(string x, string y) { throw new NotImplementedException(); } int IComparer.Compare(string x, string y) { if (x == y) return 0; string[] x1, y1; if (!table.TryGetValue(x, out x1)) { x1 = Regex.Split(x.Replace(" ", ""), "([0-9]+)"); table.Add(x, x1); } if (!table.TryGetValue(y, out y1)) { y1 = Regex.Split(y.Replace(" ", ""), "([0-9]+)"); table.Add(y, y1); } int returnVal; for (int i = 0; i < x1.Length && i < y1.Length; i++) { if (x1[i] != y1[i]) { returnVal = PartCompare(x1[i], y1[i]); return isAscending ? returnVal : -returnVal; } } if (y1.Length > x1.Length) { returnVal = 1; } else if (x1.Length > y1.Length) { returnVal = -1; } else { returnVal = 0; } return isAscending ? returnVal : -returnVal; } private static int PartCompare(string left, string right) { int x, y; if (!int.TryParse(left, out x)) return left.CompareTo(right); if (!int.TryParse(right, out y)) return left.CompareTo(right); return x.CompareTo(y); } private Dictionary<string, string[]> table = new Dictionary<string, string[]>(); public void Dispose() { table.Clear(); table = null; } } }
Bu sınıfı NaturalSortComparer.cs adında kaydederek projemize dahil ediyoruz. Artık order by kullanırken bu sıralama sınıfını parametre olarak göndereceğiz:
.OrderBy(t=>t.dokumankodu,new NaturalSortComparer<string>())
Artık sıralamamız şu şekilde olacak:
doküman1 doküman3 doküman9 doküman10 doküman11
Faydalı olması dileğiyle.