[英]Sort field that contains numbers and letters
我有一個numbers
和number-letter
和letter-number
numbers
的列表。我的列的類型是字符串。我的數據是這樣的:
1
14
3
S-34
2
36-1/E
26
S-14
20
S-2
19
36-1
30
35
S-1
34
但我想這樣排序:
1
2
3
14
20
25
30
35
36-1
36-1/E
S-1
S-2
S-14
S-34
但我的代碼對數據進行排序如下:
1
14
19
2
20
25
3
30
35
36-1
36-1/E
S-1
S-14
S-2
S-34
我的代碼是:
List<ViewTestPackageHistorySheet> lstTestPackageHistorySheets = _reportTestPackageHistorySheetRepository.ShowReport(Id).OrderBy(i => i.JointNumber).ToList();
我更改了下面的代碼,但失敗了。
List<ViewTestPackageHistorySheet> lstTestPackageHistorySheets = _reportTestPackageHistorySheetRepository.ShowReport(Id).OrderBy(i => Convert.ToInt32(i.JointNumber)).ToList();
錯誤是:
LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression.
使用以下Alphanumericsorter,它在內部使用PInvoke
public class AlphaNumericSorter : IComparer<string>
{
public int Compare(string x, string y)
{
return SafeNativeMethods.StrCmpLogicalW(x, y);
}
}
[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(string psz1, string psz2);
}
用法:
List<string> testList = // Your input list;
testList.Sort(new AlphaNumericSorter());
現在, testList
包含問題中預期的排序數據
創建一個自定義Comparer<string>
並實現您想要的邏輯(當然,對於大型列表來說它是低效的,您應該調整它):
var data = list.OrderBy(x => x, new SpecialComparer());
SpecialComparer
public class SpecialComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (x.Equals(y))
return 0;
int yn;
int xn;
bool isXNumber = int.TryParse(x, out xn);
bool isYNumber = int.TryParse(y, out yn);
if (isXNumber && isYNumber)
{
return xn.CompareTo(yn);
}
else if (isXNumber && !isYNumber)
{
return -1;
}
else if (!isXNumber && isYNumber)
{
return 1;
}
else if(x.Any(c => c == '/' || c == '-' ) || y.Any(c => c == '/' || c == '-'))
{
var xParts = x.Split("/-".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var yParts = y.Split("/-".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var minLen = Math.Min(xParts.Length, yParts.Length);
var result = 0;
for (int i = 0; i < minLen; i++)
if ((result = Compare(xParts[i], yParts[i])) != 0)
return result;
return x.Length < y.Length ? -1 : 1;
}
else
{
return x.CompareTo(y);
}
}
}
Linq
to Entities不支持Convert.ToInt32
,這是導致您的情況出錯的原因,我建議實現查詢,然后應用您的訂購。
List<ViewTestPackageHistorySheet> lstTestPackageHistorySheets = _reportTestPackageHistorySheetRepository.ShowReport(Id).ToList();
// Now order the list.
lstTestPackageHistorySheets = lstTestPackageHistorySheets.Select(x=>
new
{ // split number and string
number = Regex.IsMatch(x.Split('-')[0],@"^\d+$")? int.Parse(x.Split('-')[0]): int.MaxValue,
item =x
})
.OrderBy(x=>x.number) // first order by number
.ThenBy(x=>x.item) // then order by string.
.Select(x=>x.item)
.ToList();
檢查這個Demo
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.