С данным массивом имен файлов самый простой способ сортировки по расширению файла выглядит так:
Array.Sort(fileNames,
(x, y) => Path.GetExtension(x).CompareTo(Path.GetExtension(y)));
Проблема в том, что в очень длинном списке (~ 800 КБ) сортировка занимает очень много времени, а сортировка по всему имени файла происходит быстрее на пару секунд!
Теоретически, есть способ оптимизировать его: вместо использования Path.GetExtension()
и сравнения вновь созданных строк только для расширений, мы можем предоставить Сравнение, чем сравнение существующих строк имени файла, начиная с LastIndexOf('.')
, без создания строки.
Теперь предположим, что я нашел LastIndexOf('.')
, я хочу повторно использовать нативный StringComparer .NET и применить его только к части строки после LastIndexOf('.')
, чтобы сохранить все культурные соображения. Не нашел способа сделать это.
Есть идеи?
Edit:
С идеей tanascius использовать метод char.CompareTo()
, я пришел с моим Uber-Fast-File-Extension-Comparer, теперь он сортируется по расширению в 3 раза быстрее! это даже быстрее, чем все методы, которые каким-то образом используют Path.GetExtension()
. что ты думаешь?
Редактировать 2:
Я обнаружил, что в этой реализации не учитывается культура, поскольку метод char.CompareTo()
не учитывает культуру, поэтому это не идеальное решение.
Есть идеи?
public static int CompareExtensions(string filePath1, string filePath2)
{
if (filePath1 == null && filePath2 == null)
{
return 0;
}
else if (filePath1 == null)
{
return -1;
}
else if (filePath2 == null)
{
return 1;
}
int i = filePath1.LastIndexOf('.');
int j = filePath2.LastIndexOf('.');
if (i == -1)
{
i = filePath1.Length;
}
else
{
i++;
}
if (j == -1)
{
j = filePath2.Length;
}
else
{
j++;
}
for (; i < filePath1.Length && j < filePath2.Length; i++, j++)
{
int compareResults = filePath1[i].CompareTo(filePath2[j]);
if (compareResults != 0)
{
return compareResults;
}
}
if (i >= filePath1.Length && j >= filePath2.Length)
{
return 0;
}
else if (i >= filePath1.Length)
{
return -1;
}
else
{
return 1;
}
}