2012-01-02 11 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にその注文できませんか? – DonCallisto

+0

このデータはSharepoint Listから取得したものです。 – MAC

答えて

4

私はあなたが自然の並べ替えを使用して、独自のIComparer

を作るべきだと思います

私が見つけた最高のALGOはここ

http://www.davekoelle.com/files/AlphanumComparator.csた。(LINQをしたIComparerをとることにより、LINQの順序として使用される)

はちょうどそれジェネリッククラス作り、この、使用LINQ

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を適用するために

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; 
     } 


    } 

を以下のように、店舗1283

+0

ありがとうございました。ありがとうございました。 – MAC

+0

数値チャンクがInt32をオーバーフローすると、このバージョンと元のサイトのバージョンにバグがあります。アルゴリズムの元のアプローチは、数値のチャンクをチャンクで単純に比較して、チャンクのチャンクが異なるまで単純に比較することです。バグは 'Convert.ToInt32(thisChunk.ToString());' –

1

カスタム条件に直接従うことはできません。あなたはあなた自身の比較コードを書くために

を持つことになります列のデータ型とは何か、このQuestion

1

を見てみましょう。あなたが投稿したデータは英数字のようなものです。つまり、varchar

このコード行を使用してデータテーブル内のデータを並べ替えることができます。これを一度お試しください。

datatable.DefaultView.Sort = "COLUMN_NAME ASC"; 

列は、英数字と数値の両方を持っているので、あなただけの列のデータ型を指定して、あなたの質問に言い換えることができない場合。

+0

私はこのメソッドを試していました.... – MAC

+0

私たちはできません。混合型データをソートします。 – JayOnDotNet

+0

データベースレベルでソートしようとしました。 – JayOnDotNet

1

標準DBレベルまたはDataViewタイプのソートでは、混合型の比較はサポートされていません。

あなたは、このようなDataTable.Rows.CopyTo()と同じように(アレイにオリジナルDataTableから行をコピーして、カスタムのコンパレータでArray.Sort()を呼び出すことができます。

関連する問題