我有一项任务是在DataTable中对一组值进行排序。最棘手的部分是值具有像'。'这样的特殊字符。或' - '和负值。以下图片是我目前的输出:
数据以';'分隔在图片里。 我使用以下代码对数据进行排序。
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 :(得分:2)
看起来您需要对所谓的“自然排序顺序”进行排序。
您可以使用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));
}
}