我有一个“问题”对象列表,我想按“优先级”字段对它们进行排序。
问题是“优先级”是一个字符串名称,如“HIGH”、“MEDIUM”,所以我没有可以排序的 ID。如何排序并告诉分拣机“HIGH”高于“MEDIUM”,而“MEDIUM”又高于“LOW”?
我有一个“问题”对象列表,我想按“优先级”字段对它们进行排序。
问题是“优先级”是一个字符串名称,如“HIGH”、“MEDIUM”,所以我没有可以排序的 ID。如何排序并告诉分拣机“HIGH”高于“MEDIUM”,而“MEDIUM”又高于“LOW”?
显而易见的方法是:
string[] priorities = { "LOW", "MEDIUM", "HIGH" };
var orderedIssues = issues.OrderByDescending
(issue => Array.IndexOf(priorities, issue.Priority));
但考虑使用枚举:
public enum Priority
{
Low,
Medium,
High
}
var orderedIssues = issues.OrderByDescending
(issue => (Priority)Enum.Parse(typeof(Priority), issue.Priority, true));
更好的是使用枚举类型作为属性/字段本身的类型,在这种情况下它很简单(并且不太容易出错):
var orderedIssues = issues.OrderByDescending(issue => issue.Priority);
在这种特定情况下,您也可以使用 Linq 的OrderBy
方法:
var sortedList = issueList.OrderBy(i=>
i.Priority == "HIGH"
? 1
: i.Priority == "MEDIUM"
? 2
: 3).ToList();
作为一个单线,这不会太糟糕。您还可以按照您希望它们排序的顺序将字符串放入数组、列表或字典中(或者在字典的情况下包含排序顺序作为值)。
使用 OrderBy 的一个缺点是它不会影响源列表,除非您通过将列表重新分配给结果来告诉它。在所有情况下,它将创建两个额外的集合;OrderBy 内部使用的数组或列表(排序必须了解它们正在排序的整个集合)和由 ToList() 生成的列表。因此,这将需要 O(2N) 额外的内存,而 List.Sort() 可能是就地的(不确定它是否真的是,但它确实使用了通常就地的 QuickSort)。
最简单的方法可能是:
private static int MapPriority(string priority)
{
switch(priority.ToUpperInvariant())//skip the case bit if safe
{
case "HIGH":
return 1;
case "MEDIUM":
return 2;
case "LOW":
return 3;
default:
return 4;
}
}
var sorted = someCollection.OrderBy(i => MapPriority(i.PriorityProperty));
使用 db 支持的表单,您需要在 DB 中调用一个函数。这仅在内存中。
有很多可能的值,我会根据字典而不是手动编码。不过,在这种情况下,我会为三个手动编码(除非使用的值可能会改变,否则会进一步复杂化,使基于字典的方法成为唯一的方法)。
如果对大量此类项目进行排序,或者经常调用它,我会选择IComparer<T>
实现,或者让项目本身实现IComparable<T>
。
public enum Priority
{
LOW = 1,
MEDIUM = 2,
HIGH = 3
}
issues.OrderByDescending(issue=>issue.Priority);
像这样的东西:
List<Issue> issues = ...;
var result = issues.OrderBy(x=> x.Priority=="HIGH"?1:x.Priority=="MEDIUM"?2:3);