.net Linq ile String’i Alfabetik Sıralama

.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.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir