Как правильно отсортировать столбец с строковым номером в DataTable
Я пытаюсь отсортировать столбец с номерами строк, например, N1, N10, N100, N2, и я ожидаю результатов N1, N2, N10, N100, но сортировка не работает, я получаю те же значения N1, N10, N100, N2 в том же порядке.
Я написал следующий код.
static class ExtensionMethod
{
public static DataTable SortAlphaNumeric(this DataTable datatable, string columnName)
{
return datatable.AsEnumerable()
.OrderBy(r => r.Field<String>(columnName), new CustomComparer())
.CopyToDataTable();
}
}
public class CustomComparer : IComparer<string>
{
public int Compare(string x, string y)
{
var numberX = Regex.Match(x, @"\d+").Value;
var numberY = Regex.Match(y, @"\d+").Value;
var alphaX = Regex.Match(x, @"[^a-z]").Value;
var alphaY = Regex.Match(y, @"[^a-z]").Value;
if (alphaX.CompareTo(alphaY) == 0)
return numberX.CompareTo(numberY);
else if (alphaX.CompareTo(alphaY) < 0)
return -1;
return 1;
}
}
// Code example
class TestExample
{
public void Test()
{
var dt = new DataTable();
dt.Columns.Add("AlphaNumeric", Type.GetType("System.String"));
var row = dt.NewRow();
row["AlphaNumeric"] = "N1";
dt.Rows.Add(row);
row = dt.NewRow();
row["AlphaNumeric"] = "N10";
dt.Rows.Add(row);
row = dt.NewRow();
row["AlphaNumeric"] = "N100";
dt.Rows.Add(row);
row = dt.NewRow();
row["AlphaNumeric"] = "N2";
dt.Rows.Add(row);
var orderedDt = dt.SortAlphaNumeric("AlphaNumeric");
}
}
3 ответа
Изменение в вашем Comparer:
var numberX = int.Parse(Regex.Match(x, @"\d+").Value);
var numberY = int.Parse(Regex.Match(y, @"\d+").Value);
Я бы использовал (?<alpha>[A-Za-z])(?<number>\d+)
как регулярное выражение и сравнить alpha
(сравнение строк), а затем, если он равен, int.Parse
number
и сравнить это (целочисленное сравнение).
Это дает только два выполнения регулярных выражений вместо четырех (вероятно, компиляция регулярного выражения и помещение его в статическое поле также сделает его быстрее), и 2
будет меньше чем 10
если вы сравните реальные цифры. Если вы не анализируете числа, вы можете пропустить все регулярные выражения и просто сделать одно сравнение строк.
Если числовой формат является детерминированным (всегда строка + целое число), вы можете просто сохранить их в двух отдельных полях (в идеале, обратно в БД. Составные ключи - вещь в конце концов). Тогда это "сортировка по строке сначала, номер 2".
Если это не так, вещи будут жесткими. То, что вы хотите, это довольно необычная сортировка, которую Windows делает с файлами. Помимо пользовательских решений регулярных выражений (но, опять же, если это тот детерминист, который вы, вероятно, можете использовать 2 или более полей), был бы StrCmpLogicalW. Но и тот, и другой неуправляемый, и его поведение различается между Windows (это "каноническая" сортировка для Windows, на которой он работает, но эта сортировка варьировалась между версиями Windows).