Joe*_*ran 5 sql linq linq-to-objects sql-order-by
我今天遇到了一件有趣的事情,我以前从未注意过.似乎SQL和LINQ对AlphaNumeric字符串的顺序不同.
数据表包含行:A G 6 P 1 D J 2 T Z 9 F 0
如果我在SQL中执行Order By,我会收到以下结果:A D F G J P T Z 0 1 2 6 9
现在考虑这个LINQ示例:
class Program
{
static void Main(string[] args)
{
var list = new List<string>()
{
"A",
"G",
"6",
"P",
"1",
"D",
"J",
"2",
"T",
"Z",
"9",
"F",
"0"
};
Console.WriteLine("Default Order:");
list.ForEach(s => Console.WriteLine(s));
Console.WriteLine();
Console.WriteLine("Sorted Order:");
foreach (string s in list.OrderBy(f => f))
{
Console.WriteLine(s);
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出为0 1 2 6 9 A D F G J P T Z.
因此,SQL将字母放在第一个和第二个数字的位置,LINQ首先命令数字,然后命令字母2.我把这些结果放在DataGrid中并点击了标题,当然它也命令了一个LINQ,所以这可能是一个更深层次的鸿沟,就像在.NET/Windows级别一样.
我遇到的问题是我的用户期望他们习惯看到SQL排序的结果.如何使LINQ以相同的方式运行?
答案在下面标出,但是对于那些后来遇到这种情况的人来说,我想回顾一下,因为它需要一些答案来解决问题.
1)dcp立即进入我的大脑没有的地方:数据源.问题是使用EBCDIC排序的IBM SQL与使用ASCII排序的已知Universe中的所有其他技术之间的区别.感谢IBM再次提醒我为什么我现在是.NET开发人员.
2)认识到这一点,艾哈迈德提供了一个非常优雅的解决方案,也让我望而却步:自定义IComparer <string>.我使用了他提供的代码,并根据需要对List进行了排序.
感谢StackOverflow再次出现!
在昨天的帖子之后我完成了这个并希望分享最终结果.
昨天的帖子是一个简单的单个字符列表,但实际上它们嵌入了更长的字符串.为了使这个工作更长的字符串,我将原始的字符串比较器更改为字符比较器,然后循环遍历字符串并比较每个字符,直到我找到不匹配或用完字符进行比较.以下是最后两个Comparer类:
public class EbcdicCharComparer:IComparer {public int Compare(char x,char y){int xNum,yNum; bool xIsNum = Int32.TryParse(x.ToString(),out xNum); bool yIsNum = Int32.TryParse(y.ToString(),out yNum);
// compare numbers
if (xIsNum && yIsNum)
{
return xNum.CompareTo(yNum);
}
// compare num to char
if (xIsNum)
{
return 1;
}
// compare num to char
if (yIsNum)
{
return -1;
}
// compare normally
return x.CompareTo(y);
}
Run Code Online (Sandbox Code Playgroud)
}
public class EbcdicStringComparer:IComparer {public int Compare(string x,string y){var xArr = x.ToCharArray(); var yArr = y.ToCharArray();
var iterations = xArr.Length > yArr.Length ? yArr.Length : xArr.Length;
var charComp = new EbcdicCharComparer();
for (int i = 0; i < iterations; i++)
{
var compValue = charComp.Compare(xArr[i], yArr[i]);
if (compValue != 0)
return compValue;
}
// compare as strings
return x.CompareTo(y);
}
Run Code Online (Sandbox Code Playgroud)
}
真实数据更像是这样的:
根据需要,比较器现在按以下顺序返回数据:
再次感谢所有帮助过的人.
您可以使用接受 IComparer 的重载 OrderBy 方法。IComparer 会比较项目以产生所需的结果:
public class CustomComparer : IComparer<string>
{
public int Compare(string x, string y)
{
double xNum, yNum;
bool xIsNum = Double.TryParse(x, out xNum);
bool yIsNum = Double.TryParse(y, out yNum);
// compare numbers
if (xIsNum && yIsNum)
{
return xNum.CompareTo(yNum);
}
// compare num to string
if (xIsNum)
{
return 1;
}
// compare num to string
if (yIsNum)
{
return -1;
}
// compare as strings
return x.CompareTo(y);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
list.OrderBy(i => i, new CustomComparer())
Run Code Online (Sandbox Code Playgroud)
该实现可以用于Int32.TryParse您的特定示例数据,但我Double只是在列表中有“3.0”等情况下使用。当然,您需要了解您的数据。如果该值太大,您将需要使用适当的 TryParse 方法。
| 归档时间: |
|
| 查看次数: |
3005 次 |
| 最近记录: |