Orderby() 没有正确排序数字 c#
Posted
技术标签:
【中文标题】Orderby() 没有正确排序数字 c#【英文标题】:Orderby() not ordering numbers correctly c# 【发布时间】:2010-03-09 15:17:22 【问题描述】:我正在为我的公司编写一个应用程序,目前正在开发搜索功能。当用户搜索项目时,我想显示最高版本(存储在数据库中)。
问题是,版本存储为字符串而不是 int,当我对结果执行 OrderBy(q=>q.Version) 时,它们会返回
1
10
11
2
3
...
显然 2 在 10 之前。
有没有办法让我将版本转换为整数,或者那里有一个简单的 IComparer?到目前为止,我找不到任何实质性的东西。
我试过这样做:
var items = (from r in results
select r).OrderBy(q => Int32.Parse(q.Version));
这可以编译但不起作用。
【问题讨论】:
我会在你的问题结束时准确地建议你做了什么(按q => int.Parse(q.Version)
排序); “不起作用”是什么意思?
也许你的问题在这里:(q => Int32.Parse(q.Version))
。是否应该只是 (q => Int32.Parse(q))
以与下面的工作版本保持一致?
查看枚举结果时收到此错误消息:“方法 'Int32 Parse(System.String)' 没有支持的 SQL 转换”
@MusiGenesis:达西正在过滤具有Version
属性的某个对象的集合; int.Parse
不适用。
啊,所以您使用的是 LINQ to SQL...下面的所有答案都提供了在简单集合(例如数组)上调用 OrderBy
的方法。
【参考方案1】:
Int32.Parse 不受 LinqToSql 转换器的支持。支持 Convert.ToInt32。
http://msdn.microsoft.com/en-us/library/sf1aw27b.aspx
http://msdn.microsoft.com/en-us/library/bb882655.aspx
【讨论】:
这是最好的答案。我不必以这种方式将其转换为列表 请注意如果某个角色潜入您的数据中会产生什么后果。【参考方案2】:您的问题在其他地方,以下工作:
new[] "1", "10", "2", "3", "11"
.OrderBy(i => int.Parse(i))
.ToList()
.ForEach(Console.WriteLine);
如果您的问题是 LINQ to SQL,那么正在发生的事情是 CLR 试图从您的 LINQ 中创建 SQL 并且不理解 int.Parse
。您可以做的是首先从 SQL 中获取数据,然后在加载所有数据后对其进行排序:
var items = (from r in results
select r)
.ToList()
.OrderBy(q => Int32.Parse(q.Version));
应该这样做。
【讨论】:
在查看枚举结果时收到此错误消息:“方法 'Int32 Parse(System.String)' 没有支持的 SQL 转换”。 @CodeBlend 此语句适用于 Linq to Objects。 我的坏-1删除和删除评论 在我的主键上使用 .OrderByDescending 对我来说没问题 .OrderByDescending(i => int.Parse(i.myprimarykey))【参考方案3】:如果您无法更改表定义(因此版本是数字类型),并且您的查询确实如所列(您没有使用跳过或采取,或以其他方式减少结果数量),最好你可以做的是在未排序的结果上调用“ToList”,然后当你对其应用 OrderBY lambda 时,它将在你的代码中发生,而不是尝试在 SQL Server 端执行它(现在应该可以工作)。
【讨论】:
啊,这行得通。为什么这在 linq 语句中不起作用?因为在 linq 中它试图在服务器端进行大小写? @Darcy:看这里...atrevido.net/blog/2007/09/05/… 请注意,您也可以使用AsEnumerable
代替ToList
,它将查询提供程序改回 linq-to-objects,但保留 linq 查询的延迟执行语义而不是强制执行。
@Greg - 是的。我只是选择了最直接的方法(在本地提取结果)。最佳选择取决于 items 变量的使用方式。【参考方案4】:
有一段很棒的代码在自然排序方面做得很好。它的名字是@987654321@
。
示例代码:
var ordered = Database.Cars.ToList().OrderBy(c => c.ModelString, new AlphanumComparator());
请注意,列表必须在内存中。
如果您获得 C# 版本,请执行以下操作:
AlphanumComparator : IComparer<string>
和
public int Compare(string x, string y)
【讨论】:
@gavin:如果您打算在数据库端执行查询,当然它不会起作用。要比较的值必须在内存中使用.ToList()
之类的东西,以便 AlphanumComparator
可以完成它的工作。 :)【参考方案5】:
为什么要在 lambda 中排序?为什么不在查询中排序?
var query = from r in items
orderby int.Parse( r )
select r;
既然我们知道您正在使用 LINQ to SQL,您可能会考虑通过执行以下操作对此进行标准 SQL 调用:
Select ..., Cast( TextWhichShouldBeIntCol As int ) As IntCol
From ...
甚至
Select ..., Cast( TextWhichShouldBeIntCol As int ) As IntCol
From ...
Order By Cast( TextWhichShouldBeIntCol As int )
这将作为 int 流入您的 LINQ(如果您使用第二次迭代,请订购)。这避免了必须在 LINQ 中遍历结果集两次(一次用于查询,一次用于排序)。
【讨论】:
无论哪种方式都是一样的。 不,它在性能上确实不同 - 数据库具有良好的排序过程,有些可以并行处理构建结果集,因此数据库中的排序通常会更快,很少会变慢。 不仅如此,您还会在列表中循环两次:一次用于查询,一次用于 lambda。【参考方案6】:我做了一个测试。我有以下代码。
string[] versions = "1", "2", "10", "12", "22", "30" ;
foreach (var ver in versions.OrderBy(v => v))
Console.WriteLine(ver);
正如预期的那样,结果是 1, 10, 12, 2, 22, 30
然后让我们将versions.OrderBy(v => v))
更改为versions.OrderBy(v => int.Parse(v)))
。它工作正常:1、2、10、12、22、30
我认为您的问题是您的字符串中有非数字字符,例如“。”。你得到什么样的异常?
【讨论】:
【参考方案7】:试试这个:
var items = results.(Select(v => v).OrderBy(v => v.PadLeft(4));
这将在 Linq2Sql 中工作
【讨论】:
【参考方案8】:如果只需要“最高版本”,为什么还要排序?如果你使用 Max(),听起来你可以避免一些开销。
另外,您确实应该将列类型更改为整数。
【讨论】:
之所以不能使用Max
是因为我需要每一项的最高版本。项目类似于“name_423_1”,其中 1 是版本号。可能有“name_423_2”和“differentName_234_1”【参考方案9】:
var items = (from r in results
select r).OrderBy(q => Convert.ToInt32(q.Version));
一定要跑……
【讨论】:
【参考方案10】:听起来你有一个文本值而不是一个数值。
如果需要排序,可以试试:
var items = (from r in results
select r);
return items.OrderBy( v=> Int.Parse(v.Version) );
【讨论】:
【参考方案11】:var query = from r in items
let n = int.Parse(r)
orderby n
select n;
【讨论】:
【参考方案12】:var items = (from v in results
select v).ToList().OrderBy(x => int.Parse(x.Version));
【讨论】:
以上是关于Orderby() 没有正确排序数字 c#的主要内容,如果未能解决你的问题,请参考以下文章
SQLite Random() 在 ORDER BY 中没有正确排序
MySQL order by关键字详解,order by排序