2016-05-17 15 views
1

DataTableの値のセットをソートするタスクがあります。トリッキーな部分は、値に '。'のような特殊文字があることです。または ' - 'と負の値も使用できます。次の画像は私の現在の出力です: enter image description here値のセットを特殊文字で並べ替える

データは ';'で区切られています。写真の中の。 次のコードを使用してデータを並べ替えています。

DataTable myDataTable = new DataTable(); 
     myDataTable.Columns.Add("SN", typeof(string)); 
     string myValues = ""; 

     if (!File.Exists("d:\\DUDBC-values.txt")) //DUDBC-values.txt 
     { 
      Console.WriteLine("No file found"); 
      Console.ReadKey(); 
      return; 
     } 
     StreamReader file = new StreamReader("d:\\DUDBC-values.txt"); 
     string line; 
     while ((line = file.ReadLine()) != null) 
     { 
      myValues += line; 
      myValues += ";"; 
     } 
     file.Close(); 


     string[] myValuesArray = myValues.Split(';'); 
     myValuesArray = myValuesArray.Take(myValuesArray.Count() - 1).ToArray(); 

     foreach (string myValue in myValuesArray) 
     { 
      DataRow myRow = myDataTable.NewRow(); 
      myRow["SN"] = myValue; 
      myDataTable.Rows.Add(myRow); 
     } 

     string beforeSort = string.Join(";", myDataTable.AsEnumerable().Select(x => x["SN"])); 
     Console.WriteLine("Before Sorting:"); 
     Console.WriteLine(); 

     Console.WriteLine(beforeSort); 

     Console.WriteLine(); 


     IEnumerable<DataRow> sortedValues = myDataTable.AsEnumerable() 
               .OrderBy(x => 
               { 
                string currentStringValue = x["SN"].ToString(); 
                char[] SplitChar = new char[] { '.', '-' }; 
                string[] currentStringValueArray = new string[1]; 
                try 
                { 
                 float val = float.Parse(currentStringValue); 
                 currentStringValueArray[0] = currentStringValue; 

                } 
                catch { 
                currentStringValueArray = currentStringValue.Split(SplitChar); 
                } 

                string currentPart = ""; 
                int currentPartNumeric = 0; 


                if (currentStringValueArray.Length > 1) 
                { 
                 for (int i = 0; i < currentStringValueArray.Length; i++) 
                 { 
                  if (int.TryParse(currentStringValueArray[i], out currentPartNumeric)) 
                  { 
                   if (i >= 1) 
                    currentPart += "."; 
                   currentPart += currentPartNumeric.ToString(); 
                  } 
                  else 
                  { 
                   try 
                   { 
                    if (i >= 1) 
                     currentPart += "."; 
                    currentPart += (((int)(char.ToUpper(char.Parse(currentStringValueArray[i])))) - 64).ToString(); 
                   } 
                   catch { } 
                  } 

                 } 
                 return Convert.ToString(currentPart, CultureInfo.InvariantCulture); 
                } 

                else 
                 return 0m.ToString(); 
               }); 
string afterSort = string.Join(";", sortedValues.Select(x => x["SN"])); 
     Console.WriteLine("After Sorting:"); 
     Console.WriteLine(); 

     Console.WriteLine(afterSort); 
     //Copy to your existing datatable 
     myDataTable = sortedValues.CopyToDataTable(); 
     Console.ReadKey(); 
私はこのようになり、それを期待していた

:私が間違って何をやっている

-1 
1.1.a.1 
1.2.a.1 
1.2.a.2 
1.2.a.3 
1.3.1 
2.1.2 
2.1a.1 
2.1a.2 
2.5 
2.6.1 
2.7.1 
2.7.2 
2.7.16 
2.25a 
2.25b 
2.42.1 
2.42.2 
3.1.1 
3.1.2 
3.5.2 
3.6a.1 
3.6a.2 
3.6b.2 
5.1a.1 
5.1a.2 
5.1a.3 
5.1b.1 
5.1b.2 
5.1b.6 
6.3.1 
6.3.2 
6.3.3 
6.3.4 
6.3.5 
6.5.1 
6.5.2-C11 
6.5.3-C12 
17.06.01.b.i 
17.06.02.b.i 
17.06.02.b.vi 
18.01.b 
18.02.01.b.iii 
1000 

?必要なヘルプをお願いします。このタイプの質問in this postには、ユーザーがさまざまな種類の値を入力し続けるまで、私は質問しました。

+0

OK。しかし、何が問題なの?あなたは、ソートをどのように作りたいのか、実際にあなたのコードを使って何を作るのかを説明していません。 – ChrisF

+0

申し訳ありませんが、今質問を編集しました。 – Skaranjit

答えて

2

"Natural sort order"をソートする必要があるようです。

Windows API関数StrCmpLogicalW()があり、このような比較を行うことができます。

あなたはとてもようList<T>または配列をソートするための拡張メソッドのセットでこれをラップすることができます:

public static class NaturalSortExt 
{ 
    /// <summary>Sorts a list in "Natural sort order", i.e. "9" sorts before "10".</summary> 
    /// <typeparam name="T">The type of elements in the list to be sorted.</typeparam> 
    /// <param name="self">The list to be sorted.</param> 
    /// <param name="stringSelector">A projection to convert list elements to strings for comparision.</param> 

    public static void SortNatural<T>(this List<T> self, Func<T, string> stringSelector) 
    { 
     self.Sort((lhs, rhs) => StrCmpLogicalW(stringSelector(lhs), stringSelector(rhs))); 
    } 

    /// <summary>Sorts a list in "Natural sort order", i.e. "9" sorts before "10".</summary> 
    /// <param name="self">The list to be sorted.</param> 

    public static void SortNatural(this List<string> self) 
    { 
     self.Sort(StrCmpLogicalW); 
    } 

    /// <summary>Sorts an array in "Natural sort order", i.e. "9" sorts before "10".</summary> 
    /// <param name="self">The array to be sorted.</param> 

    public static void SortNatural(this string[] self) 
    { 
     Array.Sort(self, StrCmpLogicalW); 
    } 

    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] 
    static extern int StrCmpLogicalW(string lhs, string rhs); 
} 

次に、あなただけの以下のサンプルコードで示されたように、あなたの配列(またはList<T>)を並べ替えることができます。

class Program 
{ 
    static void Main() 
    { 
     string[] test = 
     { 
      "3.1.2", 
      "1.2.a.1", 
      "1.2.a.2", 
      "1.3.1", 
      "2.1.2", 
      "2.1a.2", 
      "2.1a.1", 
      "-1", 
      "2.5", 
      "2.7.1", 
      "1.1.a.1", 
      "2.7.16", 
      "2.7.2", 
      "2.25a", 
      "2.6.1", 
      "5.1a.3", 
      "2.42.2", 
      "2.25b", 
      "2.42.1", 
      "3.6a.2", 
      "5.1b.1", 
      "3.1.1", 
      "3.5.2", 
      "3.6a.1", 
      "3.6b.2", 
      "5.1a.1", 
      "1.2.a.3", 
      "5.1b.2", 
      "5.1b.6", 
      "6.3.1", 
      "6.3.2", 
      "17.06.02.b.i", 
      "6.3.3", 
      "5.1a.2", 
      "6.3.4", 
      "6.3.5", 
      "6.5.1", 
      "1000", 
      "6.5.2-C11", 
      "6.5.3-C12", 
      "17.06.01.b.i", 
      "17.06.02.b.vi", 
      "18.01.b", 
      "18.02.01.b.iii" 
     }; 

     string[] expected = 
     { 
      "-1", 
      "1.1.a.1", 
      "1.2.a.1", 
      "1.2.a.2", 
      "1.2.a.3", 
      "1.3.1", 
      "2.1.2", 
      "2.1a.1", 
      "2.1a.2", 
      "2.5", 
      "2.6.1", 
      "2.7.1", 
      "2.7.2", 
      "2.7.16", 
      "2.25a", 
      "2.25b", 
      "2.42.1", 
      "2.42.2", 
      "3.1.1", 
      "3.1.2", 
      "3.5.2", 
      "3.6a.1", 
      "3.6a.2", 
      "3.6b.2", 
      "5.1a.1", 
      "5.1a.2", 
      "5.1a.3", 
      "5.1b.1", 
      "5.1b.2", 
      "5.1b.6", 
      "6.3.1", 
      "6.3.2", 
      "6.3.3", 
      "6.3.4", 
      "6.3.5", 
      "6.5.1", 
      "6.5.2-C11", 
      "6.5.3-C12", 
      "17.06.01.b.i", 
      "17.06.02.b.i", 
      "17.06.02.b.vi", 
      "18.01.b", 
      "18.02.01.b.iii", 
      "1000" 
     }; 

     test.SortNatural(); 

     Debug.Assert(test.SequenceEqual(expected)); 

     Console.WriteLine(string.Join("\n", test)); 
    } 
} 
+0

イエス・キリスト。私は何度もホイールを発明しました。ありがとうございました! – Eugene

+0

はい、それは私の多くのデータに必要なものでしたが、負の値の場合は失敗しています。しかし、私はいくつかの制約を置くことを考えています。すべてがすべて機能します。ありがとう:D – Skaranjit

関連する問題