2013-03-20 40 views
0

Ive得到了如下的LINQ查询: -LINQ数字排序取代非数字字符

(from a in MyData 
where a.Field1.Replace(" ","").Contains("ABCDEFG") 
select a.Field2).Take(50) 

它返回: -

114         
115         
115 A        
116         
116 A        
118         
119         
122         
124         
128         
131         
132         
133         
95         
96         
97         
98         
99 

我需要能够以数字排序这个名单,我可以这样做: -

(from a in MyData 
where a.Field1.Replace(" ","").Contains("ABCDEFG") 
select a.Field2).Take(50).OrderBy(x => Convert.ToInt32(x)) 

问题是这样的回报: -

Conversion failed when converting the nvarchar value '111 A ' to data type int. 

因为它显然不能将'111 A '转换为整数。

是否有任何方法去除所有非数字字符只是为了排序?

+0

你想要的是一种自然排序。网络上有大量的资源。基本上,创建一个自定义'IComparer ',它实现自然排序并将它的一个实例传递给OrderBy:'OrderBy(x => x,new NaturalStringComparer())'。 – 2013-03-20 14:41:00

+0

TO支持以前的评论:这里的关于在C#中的自然排序的stackoverflow问题:http://stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp – J0HN 2013-03-20 14:41:38

+0

@DanielHilgarth它看起来像他正在使用LINQ to SQL,一个自定义的IComparer将不适合。 – 2013-03-20 14:42:20

回答

3

尝试:

MyData.Where(d => Field1.Replace(" ","").Contains("ABCDEFG")) 
    .AsEnumerable() 
    .OrderBy(d => Convert.ToInt32(Regex.Split(d.Field2, @"\D+")[0])) 
    .Take(50) 
    .Select(d => d.Field2); 

可以交换排序依据(),并根据您所需的结果,可以采取()。然而,由于鲍勃淡水河谷说明如下:

如果采取()是第一,那么它应该是AsEnumerable()

,这样你就不会从源加载所有的记录之前。

+0

如果'Take()'是第一个,那么它应该放在'AsEnumerable()'之前。 – 2013-03-20 14:54:40

+0

欢呼声,更新回答 – Oliver 2013-03-20 14:59:14

+0

'Take'并不代表任何事情,除非集合首先从源代码排序 - 所以对我来说,做自定义(非数据库)排序并返回前50名将整个结果集放入内存中,然后运行自定义的'OrderBy',然后运行'Take'。我知道只返回从数据库中排序的前50个数据的唯一方法是在原始查询(通过存储过程或视图或其他东西)中进行自定义排序,而不是简单的LINQ2SQL或EF。 – 2013-03-20 15:03:40

0

不是最漂亮的代码,但是在您的排序lambda中,您可以创建一个仅由数字组成的新字符串,然后将其转换为您的排序值的整数。

.OrderBy(x => 
    Convert.ToInt32(new string(x.Where(c => char.IsDigit(c)) 
           .ToArray() 
          ) 
        ) 
     );