我想這個名單排序號碼,則字符串C#
A
B
C
111
11
123
1
42
5
進行排序
1
5
11
42
111
123
A
B
C
默認情況下,它像串(所以,它會1,11,111,123,42,5排序號碼), 但我想排序數字像數字,而不是數字的字符串。
是否有乾淨的解決方案來排序它像上面?
這是一個對象列表,而對象有幾個屬性,其中之一就是這個字符串。
我想這個名單排序號碼,則字符串C#
A
B
C
111
11
123
1
42
5
進行排序
1
5
11
42
111
123
A
B
C
默認情況下,它像串(所以,它會1,11,111,123,42,5排序號碼), 但我想排序數字像數字,而不是數字的字符串。
是否有乾淨的解決方案來排序它像上面?
這是一個對象列表,而對象有幾個屬性,其中之一就是這個字符串。
這對於大多數使用情況下工作,但如果字符串控制字符開頭可能有奇怪的結果,串像「\ TABC」會在整數前:
list.OrderBy(x=>int.TryParse(x, out var dummy) ? dummy.ToString("D10") : x);
或C#的先前版本到7:
list.OrderBy(x=> { int dummy; return int.TryParse(x, out dummy) ? dummy.ToString("D10") : x;});
你知道你可以做'dummy.ToString(「D10」)'而不是另一個解析。 – juharr
@juharr更新的答案不需要兩個解析,並添加了C#7.0版本。 –
您可以遍歷所有值一次,並使用int.TryParse將它們分成兩個單獨的列表:一個用於int.TryParse返回true的值(又名數字),另一個列表用於其中的值返回false(非數字)。然後你可以分別對這兩個列表進行排序,並在最後連接它們的排序結果。
我寫了這個IComparer
執行幾個月後回來處理這樣的事情。我認爲它會默認做你想做的事情,儘管它是爲處理更復雜的情況而設計的,其中數字/字母組由分隔符分隔,而分隔符也需要以原子方式分類。你應該能夠根據你的需求進行調整。
public class SemanticComparer : IComparer<string>
{
private static Regex _splitter = new Regex("\\W+");
public int Compare(string x, string y)
{
string[] partsX = _splitter.Split(x);
string[] partsY = _splitter.Split(y);
int shortest = Math.Min(partsX.Length, partsY.Length);
for (int index = 0; index < shortest; index++)
{
int intX, intY;
int result;
if (int.TryParse(partsX[index], out intX) && int.TryParse(partsY[index], out intY))
{
result = intX.CompareTo(intY);
}
else
{
result = string.Compare(partsX[index], partsY[index], StringComparison.Ordinal);
}
if (result != 0)
{
return result;
}
}
return 0;
}
}
您可以像這種用它列表:
MyList.Sort(new SemanticComparer());
你想要什麼叫Natural sort。
我曾經寫了一些代碼:
public static class NaturalCompare
{
public static int Compare(string first, string second, StringComparison comparison = StringComparison.Ordinal)
{
if (string.Compare(first, second, comparison) == 0)
{
return 0;
}
if (first == null)
{
return -1;
}
if (second == null)
{
return 1;
}
DateTime d1, d2;
if (DateTime.TryParse(first, out d1) && DateTime.TryParse(second, out d2))
{
return d1.CompareTo(d2);
}
var pos1 = 0;
var pos2 = 0;
int result;
do
{
bool isNum1, isNum2;
var part1 = GetNext(first, ref pos1, out isNum1);
var part2 = GetNext(second, ref pos2, out isNum2);
if (isNum1 && isNum2)
{
result = long.Parse(part1).CompareTo(long.Parse(part2));
}
else
{
result = String.Compare(part1, part2, comparison);
}
} while (result == 0 && pos1 < first.Length && pos2 < second.Length);
return result;
}
public static int CompareToNatural(this string first, string second, StringComparison comparison = StringComparison.Ordinal)
{
return Compare(first, second, comparison);
}
public static IOrderedEnumerable<TSource> OrderByNatural<TSource>(this IEnumerable<TSource> source, Func<TSource, string> keySelector)
{
return source.OrderBy(keySelector, new NatComparer());
}
public static IOrderedEnumerable<TSource> OrderByNaturalDescending<TSource>(this IEnumerable<TSource> source, Func<TSource, string> keySelector)
{
return source.OrderByDescending(keySelector, new NatComparer());
}
private sealed class NatComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return NaturalCompare.Compare(x, y);
}
}
private static string GetNext(string s, ref int index, out bool isNumber)
{
if (index >= s.Length)
{
isNumber = false;
return "";
}
isNumber = char.IsDigit(s[index]);
var start = index;
while (index < s.Length && char.IsDigit(s[index]) == isNumber)
{
index++;
}
return s.Substring(start, index - start);
}
}
我沒有測試性能的代碼,但是你可以用的Comparer
public class ArrayItemComparer : IComparer<string>
{
public int Compare(string x, string y)
{
int xInt = 0, yInt = 0;
bool parseX = int.TryParse(x, out xInt);
bool parseY = int.TryParse(y, out yInt);
if (parseX && parseY)
{
return xInt.CompareTo(yInt);
}
else if (parseX)
{
return -1;
}
else if (parseY)
{
return 1;
}
else
{
return x.CompareTo(y);
}
}
}
我已經創建了一個解決方案解決了這個爲了這。我將list
分爲兩部分,然後排序和連接。請檢查以下內容:
public List<ListItem> getSortedList()
{
int dummy = 0;
List<ListItem> list = new List<ListItem>();
list.Add(new ListItem() { Item = "A" });
list.Add(new ListItem() { Item = "B" });
list.Add(new ListItem() { Item = "C" });
list.Add(new ListItem() { Item = "111" });
list.Add(new ListItem() { Item = "11" });
list.Add(new ListItem() { Item = "123" });
list.Add(new ListItem() { Item = "1" });
list.Add(new ListItem() { Item = "42" });
list.Add(new ListItem() { Item = "5" });
var listNumber = list.Where(m => int.TryParse(m.Item, out dummy)).ToList().OrderBy(m => Convert.ToInt16(m.Item)).ToList();
var listString = list.Where(m => !int.TryParse(m.Item, out dummy)).ToList().OrderBy(m => m.Item).ToList();
var sortedList = listNumber.Concat(listString).ToList();
return sortedList;
}
您可以在DotNetFiddle中運行此操作。
假設你開始字符串的集合,一個簡單的比較器應該做的工作:
public class Comparer : IComparer<string>
{
public int Compare(string a, string b)
{
int ia = 0;
int ib = 0;
var aIsInt = int.TryParse(a,out ia);
var bIsInt = int.TryParse(b,out ib);
if (aIsInt == bIsInt)
{
if (aIsInt)
{
return ia.CompareTo(ib);
}
else
{
return a.CompareTo(b);
}
}
return aIsInt ? -1 : 1;
}
}
是您的列表,開始用什麼類型的?你已經嘗試了什麼? –
你的數字是以字符串表示還是整數? – Amy
https://stackoverflow.com/questions/119730/how-do-i-sort-a-varchar-column-in-sql-server-that-contains-numbers – mxmissile