我有一个numbers
和number-letter
以及letter-number
的列表。我的列类型是字符串。我的数据是这样的:
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.
答案 0 :(得分:1)
使用以下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
包含问题
答案 1 :(得分:1)
创建一个自定义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);
}
}
}
答案 2 :(得分:1)
Linq
到实体不支持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