첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

■ 자연 정렬을 하는 방법을 보여준다.

TestProject.zip
0.00MB

▶ NaturalSortingComparer.cs

using System.Text.RegularExpressions;

namespace TestProject;

/// <summary>
/// 자연 정렬 비교자
/// </summary>
/// <typeparam name="TItem">항목 타입</typeparam>
public class NaturalSortingComparer<TItem> : IComparer<string>, IDisposable
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Field
    ////////////////////////////////////////////////////////////////////////////////////////// Private

    #region Field

    /// <summary>
    /// 딕셔너리
    /// </summary>
    private Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>();

    /// <summary>
    /// 오름차순 여부
    /// </summary>
    private bool isAscending;

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 생성자 - NaturalSortingComparer(isAscending)

    /// <summary>
    /// 생성자
    /// </summary>
    /// <param name="isAscending">오름차순 여부</param>
    public NaturalSortingComparer(bool isAscending = true)
    {
        this.isAscending = isAscending;
    }

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Method
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 비교하기 - Compare(source1, source2)

    /// <summary>
    /// 비교하기
    /// </summary>
    /// <param name="source1">소스 문자열 1</param>
    /// <param name="source2">소스 문자열 2</param>
    /// <returns>비교 결과</returns>
    public int Compare(string source1, string source2)
    {
        throw new NotImplementedException();
    }

    #endregion
    #region 비교하기 - IComparer<string>.Compare(source1, source2)

    /// <summary>
    /// 비교하기
    /// </summary>
    /// <param name="source1">소스 문자열 1</param>
    /// <param name="source2">소스 문자열 2</param>
    /// <returns>비교 결과</returns>
    int IComparer<string>.Compare(string source1, string source2)
    {
        if(source1 == source2)
        {
            return 0;
        }

        string[] tokenArray1;
        string[] tokenArray2;

        if(!this.dictionary.TryGetValue(source1, out tokenArray1))
        {
            tokenArray1 = Regex.Split(source1.Replace(" ", ""), "([0-9]+)");

            this.dictionary.Add(source1, tokenArray1);
        }

        if(!this.dictionary.TryGetValue(source2, out tokenArray2))
        {
            tokenArray2 = Regex.Split(source2.Replace(" ", ""), "([0-9]+)");

            this.dictionary.Add(source2, tokenArray2);
        }

        int result;

        for(int i = 0; i < tokenArray1.Length && i < tokenArray2.Length; i++)
        {
            if(tokenArray1[i] != tokenArray2[i])
            {
                result = ComparePart(tokenArray1[i], tokenArray2[i]);

                return isAscending ? result : -result;
            }
        }

        if(tokenArray2.Length > tokenArray1.Length)
        {
            result = 1;
        }
        else if(tokenArray1.Length > tokenArray2.Length)
        {
            result = -1;
        }
        else
        {
            result = 0;
        }

        return isAscending ? result : -result;
    }

    #endregion

    #region 리소스 해제하기 - Dispose()

    /// <summary>
    /// 리소스 해제하기
    /// </summary>
    public void Dispose()
    {
        this.dictionary.Clear();

        this.dictionary = null;
    }

    #endregion

    ////////////////////////////////////////////////////////////////////////////////////////// Private

    #region 부분 비교하기 - ComparePart(source1, source2)

    /// <summary>
    /// 부분 비교하기
    /// </summary>
    /// <param name="source1">소스 문자열 1</param>
    /// <param name="source2">소스 문자열 2</param>
    /// <returns>부분 비교 결과</returns>
    private static int ComparePart(string source1, string source2)
    {
        int value1;
        int value2;

        if(!int.TryParse(source1, out value1))
        {
            return source1.CompareTo(source2);
        }

        if(!int.TryParse(source2, out value2))
        {
            return source1.CompareTo(source2);
        }

        return value1.CompareTo(value2);
    }

    #endregion
}

 

▶ Program.cs

namespace TestProject;

/// <summary>
/// 프로그램
/// </summary>
class Program
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Method
    ////////////////////////////////////////////////////////////////////////////////////////// Static
    //////////////////////////////////////////////////////////////////////////////// Private

    #region 프로그램 시작하기 - Main()

    /// <summary>
    /// 프로그램 시작하기
    /// </summary>
    private static void Main()
    {
        string[] sourceArray = new string[]
        {
            "a4",
            "a3",
            "a2",
            "a10",
            "b5",
            "b4",
            "b400",
            "1",
            "C1d",
            "c1d2"
        };

        Array.Sort(sourceArray, new NaturalSortingComparer<string>());

        foreach(string source in sourceArray)
        {
            Console.WriteLine(source);
        }
    }

    #endregion
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요