我在linqtosql中有一个返回LabelNumber的查询:
var q = from list in db.Lists
select list.LabelNumber;
Run Code Online (Sandbox Code Playgroud)
var q
然后成为一个IEnumerable<string>
像这样的元素:
{"1","2","2.A","2.B","3","3.A","3.B"}
Run Code Online (Sandbox Code Playgroud)
我基本上想要按照上面的顺序排序元素,但是我不能使用OrderBy(x=>x.LabelNumber)
因为它"10"
会在"1"
之前和之后放置"2"
.
我假设我必须编写自定义比较器函数,但我如何使用linq执行此操作?
编辑:我认为下面的所有答案都有效,但必须在所有回复中添加一个警告.
如果您使用的是Linq2SQL,则无法在查询中使用数组索引.要解决这个问题,您应该有两个查询.一个从SQL读取的.第二个是排序:
var q = from list in db.Lists
select list.LabelNumber;
var q2 = q.AsEnumerable()
.OrderBy(x => int.Parse(x.LabelNumber.Split('.')[0]))
.ThenBy(x => x.Number
.Contains(".") ?
x.LabelNumber.Split('.')[1].ToString()
:
string.Empty);
Run Code Online (Sandbox Code Playgroud)
Mic*_*pat 13
OrderBy(x=>x.LabelNumber, new AlphanumComparator())
Run Code Online (Sandbox Code Playgroud)
David Koelle AlphanumComparator
的优秀Alphanum自然排序算法在哪里?无需重新发明轮子.
如果您要使用C#版本,请将其更改为:
AlphanumComparator : IComparer<string>
Run Code Online (Sandbox Code Playgroud)
和
public int Compare(string x, string y)
Run Code Online (Sandbox Code Playgroud)
您可能不必编写自定义比较器.如果您的所有标签都在表单中number.letter
,则可以使用此标签.
var query = from list in db.Lists
let split = list.LabelNumber.Split('.')
let order = split.Length == 1
? new { a = int.Parse(split[0]), b = String.Empty }
: new { a = int.Parse(split[0]), b = split[1] }
orderby order.a, order.b
select list.LabelNumber;
Run Code Online (Sandbox Code Playgroud)
如果需要更多控制,可以始终将sortby字段(a
和b
)转换为适当的类型而不是int和字符串.
如果这是LINQ-to-SQL,则实际上这不起作用,因为这里使用的某些方法不受支持.这是一个LINQ-to-SQL友好版本.它不会产生最漂亮的查询,但它会起作用.
var query = from list in db.Lists
let dot = list.LabelNumber.IndexOf('.')
let name = list.LabelNumber
let order = dot == -1
? new { a = Convert.ToInt32(name.Substring(0, dot)), b = String.Empty }
: new { a = Convert.ToInt32(name.Substring(0, dot)), b = name.Substring(dot+1) }
orderby order.a, order.b
select list.LabelNumber;
Run Code Online (Sandbox Code Playgroud)