■ 자연 정렬을 하는 방법을 보여준다.
▶ NaturalSortingComparer.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
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 } |