này được gọi là "thứ tự sắp xếp tự nhiên", và thường được sử dụng để sắp xếp các mục như những người bạn có, như tên tập tin và như vậy .
Dưới đây là một ngây thơ (theo nghĩa rằng có lẽ nhiều unicode-vấn đề với nó) thực hiện điều đó dường như làm các trick:
Bạn có thể sao chép mã dưới đây vào LINQPad để thực hiện nó và thử nghiệm nó.
Về cơ bản các thuật toán so sánh sẽ xác định số bên trong chuỗi, và xử lý những bằng đệm một ngắn nhất với zero hàng đầu, vì vậy ví dụ hai chuỗi "Test123Abc"
và "Test7X"
nên được so sánh như thể chúng là "Test123Abc"
và "Test007X"
, mà nên sản xuất bạn muốn gì.
Tuy nhiên, khi tôi nói "ngây thơ", tôi có nghĩa là tôi có thể có tấn vấn đề unicode thực sự ở đây, giống như xử lý dấu phụ và ký tự đa điểm. Nếu bất cứ ai có thể thực hiện tốt hơn, tôi rất thích nhìn thấy nó.
Ghi chú:
- Việc thực hiện không thực sự phân tích các con số, vì vậy tùy tiện số dài nên chỉ làm việc tốt
- Vì nó không thực sự phân tích những con số như "số", số dấu chấm động sẽ không được xử lý đúng cách, "123.45" và "123.789" sẽ được so sánh là "123.045" so với "123.789", điều đó là sai.
Code:
void Main()
{
List<string> input = new List<string>
{
"1", "5", "3", "6", "11", "9", "A1", "A0"
};
var output = input.NaturalSort();
output.Dump();
}
public static class Extensions
{
public static IEnumerable<string> NaturalSort(
this IEnumerable<string> collection)
{
return NaturalSort(collection, CultureInfo.CurrentCulture);
}
public static IEnumerable<string> NaturalSort(
this IEnumerable<string> collection, CultureInfo cultureInfo)
{
return collection.OrderBy(s => s, new NaturalComparer(cultureInfo));
}
private class NaturalComparer : IComparer<string>
{
private readonly CultureInfo _CultureInfo;
public NaturalComparer(CultureInfo cultureInfo)
{
_CultureInfo = cultureInfo;
}
public int Compare(string x, string y)
{
// simple cases
if (x == y) // also handles null
return 0;
if (x == null)
return -1;
if (y == null)
return +1;
int ix = 0;
int iy = 0;
while (ix < x.Length && iy < y.Length)
{
if (Char.IsDigit(x[ix]) && Char.IsDigit(y[iy]))
{
// We found numbers, so grab both numbers
int ix1 = ix++;
int iy1 = iy++;
while (ix < x.Length && Char.IsDigit(x[ix]))
ix++;
while (iy < y.Length && Char.IsDigit(y[iy]))
iy++;
string numberFromX = x.Substring(ix1, ix - ix1);
string numberFromY = y.Substring(iy1, iy - iy1);
// Pad them with 0's to have the same length
int maxLength = Math.Max(
numberFromX.Length,
numberFromY.Length);
numberFromX = numberFromX.PadLeft(maxLength, '0');
numberFromY = numberFromY.PadLeft(maxLength, '0');
int comparison = _CultureInfo
.CompareInfo.Compare(numberFromX, numberFromY);
if (comparison != 0)
return comparison;
}
else
{
int comparison = _CultureInfo
.CompareInfo.Compare(x, ix, 1, y, iy, 1);
if (comparison != 0)
return comparison;
ix++;
iy++;
}
}
// we should not be here with no parts left, they're equal
Debug.Assert(ix < x.Length || iy < y.Length);
// we still got parts of x left, y comes first
if (ix < x.Length)
return +1;
// we still got parts of y left, x comes first
return -1;
}
}
}
Do các giá trị chuỗi đại diện cho số thập lục phân? Hoặc nó sẽ có thể cho "S2" xuất hiện trong danh sách nói? –
@El Ronnoco: Không có hệ thập lục phân. Nó có thể là "S2" vv ... (Đã chỉnh sửa) –