2012-01-02 2 views
1

데이터 테이블 열의 값을 정렬해야한다는 요구 사항이 있습니다. 이 열은 문자열, 정수 또는 혼합 텍스트를 포함합니다. 예를 들면 : 나는 그것이 순서로 결과 Dataview.sort() 방법을 사용하여 값을 정렬 할 경우 23, 18, 12, store 23, store a1, 1283, 25, ...DataTable 열 정렬을 사용자 지정하는 방법

: 12, 1283, 18, 23, 25, store 1283, store a1, ...를하지만이 같은 필요 12, 18, 23, 25, 1283, store 23, store a1, ...

이 있습니까

데이터 테이블 열은 다음과 같이 값을 포함 이 요구 사항을 달성하기위한 간단한 방법은 무엇입니까?

+0

가 직접 SQL로 그 주문 할 수 없습니다 사용 LINQ를 적용? 난 당신이 데이터 셰어 목록에서 촬영하고있다 – DonCallisto

+0

가 .. – MAC

답변

4

을 당신이

자신의 IComparer를 자연 정렬을 사용하게해야한다고 생각

내가 찾은 가장 좋은 너 한테 여기

http://www.davekoelle.com/files/AlphanumComparator.cs이었다. (LINQ는 IComparer를 필요로 Linq를 순서대로 사용하기 때문에)

는 그냥 일반적인 클래스 확인

public class AlphanumComparator<T> : IComparer<T> 
    { 
     private enum ChunkType { Alphanumeric, Numeric }; 
     private bool InChunk(char ch, char otherCh) 
     { 
      ChunkType type = ChunkType.Alphanumeric; 

      if (char.IsDigit(otherCh)) 
      { 
       type = ChunkType.Numeric; 
      } 

      if ((type == ChunkType.Alphanumeric && char.IsDigit(ch)) 
       || (type == ChunkType.Numeric && !char.IsDigit(ch))) 
      { 
       return false; 
      } 

      return true; 
     } 

     public int Compare(T x, T y) 
     { 
      String s1 = x as string; 
      String s2 = y as string; 
      if (s1 == null || s2 == null) 
      { 
       return 0; 
      } 

      int thisMarker = 0, thisNumericChunk = 0; 
      int thatMarker = 0, thatNumericChunk = 0; 

      while ((thisMarker < s1.Length) || (thatMarker < s2.Length)) 
      { 
       if (thisMarker >= s1.Length) 
       { 
        return -1; 
       } 
       else if (thatMarker >= s2.Length) 
       { 
        return 1; 
       } 
       char thisCh = s1[thisMarker]; 
       char thatCh = s2[thatMarker]; 

       StringBuilder thisChunk = new StringBuilder(); 
       StringBuilder thatChunk = new StringBuilder(); 

       while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || InChunk(thisCh, thisChunk[0]))) 
       { 
        thisChunk.Append(thisCh); 
        thisMarker++; 

        if (thisMarker < s1.Length) 
        { 
         thisCh = s1[thisMarker]; 
        } 
       } 

       while ((thatMarker < s2.Length) && (thatChunk.Length == 0 || InChunk(thatCh, thatChunk[0]))) 
       { 
        thatChunk.Append(thatCh); 
        thatMarker++; 

        if (thatMarker < s2.Length) 
        { 
         thatCh = s2[thatMarker]; 
        } 
       } 

       int result = 0; 
       // If both chunks contain numeric characters, sort them numerically 
       if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0])) 
       { 
        thisNumericChunk = Convert.ToInt32(thisChunk.ToString()); 
        thatNumericChunk = Convert.ToInt32(thatChunk.ToString()); 

        if (thisNumericChunk < thatNumericChunk) 
        { 
         result = -1; 
        } 

        if (thisNumericChunk > thatNumericChunk) 
        { 
         result = 1; 
        } 
       } 
       else 
       { 
        result = thisChunk.ToString().CompareTo(thatChunk.ToString()); 
       } 

       if (result != 0) 
       { 
        return result; 
       } 
      } 

      return 0; 
     } 


    } 

을 다음과 같이 지금이,

DataTable dt = new DataTable(); 
      dt.TableName = "Sort"; 
      dt.Columns.Add("Check"); 
      DataRow dr = dt.NewRow(); 
      dr["Check"] = "12"; 
      dt.Rows.Add(dr); 

      DataRow dr2 = dt.NewRow(); 
      dr2["Check"] = "1283"; 
      dt.Rows.Add(dr2); 

      DataRow dr3 = dt.NewRow(); 
      dr3["Check"] = "store 1283"; 
      dt.Rows.Add(dr3); 

      DataRow dr4 = dt.NewRow(); 
      dr4["Check"] = "23"; 
      dt.Rows.Add(dr4); 

      DataView dv = new DataView(); 
      dv.Table = dt; 

      AlphanumComparator<string> comparer = new AlphanumComparator<string>(); 
      //DataTable dtNew = dv.Table; 
      DataTable dtNew = dv.Table.AsEnumerable().OrderBy(x => x.Field<string>("Check"), comparer).CopyToDataTable(); 
      dtNew.TableName = "NaturalSort"; 

      dv.Table = dtNew; 

이 결과 12, 23, 1283는, 저장 1283

+0

에 추가하려고 수치 덩어리가 INT32을 오버 플로우 때를 아난드 – MAC

+0

이 버전의 원본 사이트의 버전 버그가 있습니다 감사합니다. 알고리즘의 원래 접근법은 하나가 다른 것으로 나타날 때까지 단순히 숫자 덩어리 char을 char과 비교하는 것입니다. 버그는'Convert.ToInt32 (thisChunk.ToString());' –

1

사용자 지정 기준에 직접 따라갈 수 없습니다. 당신은 당신의 자신의 비교 코드

열의 데이터 유형 이것은 무엇 Question

1

를 살펴 보자를 작성해야합니다. 당신이 게시 된 데이터는 숫자 즉, VARCHAR

당신은이 코드 줄을 사용하여 데이터 테이블의 데이터를 정렬 할 수 있습니다 같다. 한 번 해봐.

datatable.DefaultView.Sort = "COLUMN_NAME ASC"; 

그냥 열이 알파벳 및 숫자 값을 모두 가지고 있기 때문에 열의 데이터 유형을 지정 질문을 바꿔 할 수없는 경우.

+0

난이 방법을 시도했다 Dataview.sort의 모든 데이터()를 다시 가져올 필요가 없기 때문에 그것이 ..., 가장 효율적인 것이라고 생각 – MAC

+0

우리는 할 수 없습니다 혼합 유형 데이터를 정렬하십시오. – JayOnDotNet

+0

는 .. 데이터베이스 레벨에서 정렬 후가 아니라 잘 작동 데이터 테이블 – JayOnDotNet

1

표준 DB 수준 또는 DataView 유형 정렬은 혼합 유형 비교를 지원하지 않습니다.

사용자 지정 비교기와 Array.Sort()를 호출 다음과 같은 DataTable.Rows.CopyTo()와 같은 배열 (에 원래 DataTable의 행을 복사 할 수있다.

관련 문제