我正在尝试为我的基本数据类创建一个动态排序(只是一堆属性)。 以下代码演示了我要做的事情。它几乎可以工作。我唯一不明白的是为什么ThenBy似乎完全采用了这个列表。任何人都可以解释原因吗?
private void SortList(string[] sortCols)
{
bool first = true;
IOrderedEnumerable<Data> returnVal = null;
Console.WriteLine("Sorting test data");
if (sortCols.Length < 1)
return;
foreach (string col in sortCols)
{
if (first)
{
returnVal = _testData.OrderBy(p => typeof(Data).GetProperty(col).GetValue(p, null));
//Or OrderByDescending
first = false;
}
else
{
returnVal = returnVal.ThenBy(p => typeof(Data).GetProperty(col).GetValue(p, null));
//Or ThenByDescending
}
}
_testData = new List<Data>(returnVal);
}
_testData只是一个List Data类如下所示:
public class Data
{
public string Name { get; set; }
public int Age { get; set; }
public double Income { get; set; }
public bool Married { get; set; }
public override string ToString()
{
return Name + "; age=" + Age.ToString() + "; income=" + Income.ToString() + "; married=" + Married.ToString();
}
}
答案 0 :(得分:2)
Unable to duplicate your problem。一切似乎排序正确:
public static void Main()
{
var data1 = new Data() { Name = "Albert", Age = 99 };
var data2 = new Data() { Name = "Zebra", Age = 1};
var data3 = new Data() { Name = "Zebra", Age = 99};
var data4 = new Data() { Name = "Albert", Age = 1 };
_testData.Add(data1);
_testData.Add(data2);
_testData.Add(data3);
_testData.Add(data4);
SortList(new string[] { "Name", "Age" });
foreach(var data in _testData)
{
Console.WriteLine(data.ToString());
}
Console.WriteLine(string.Empty);
SortList(new string[] { "Age", "Name" });
foreach(var data in _testData)
{
Console.WriteLine(data.ToString());
}
}
结果:
对测试数据进行排序
阿尔伯特;年龄= 1;收入= 0;已婚=假
阿尔伯特;年龄= 99;收入= 0;已婚=假
斑马;年龄= 1;收入= 0;已婚=假
斑马;年龄= 99;收入= 0;已婚=假
。
对测试数据进行排序
阿尔伯特;年龄= 1;收入= 0;已婚=假
斑马;年龄= 1;收入= 0;已婚=假
阿尔伯特;年龄= 99;收入= 0;已婚=假
斑马;年龄= 99;收入= 0;已婚=假
更新(适用于.Net 4.0)
稍微更改代码可以解决问题(example):
private static void SortList(string[] sortCols)
{
Console.WriteLine("Sorting test data");
if (sortCols.Length < 1)
return;
IOrderedEnumerable<Data> returnVal = _testData.OrderBy(p => typeof(Data).GetProperty(sortCols[0]).GetValue(p, null));
foreach (string col in sortCols.Skip(1))
{
returnVal = returnVal.ThenBy(p => typeof(Data).GetProperty(col).GetValue(p, null));
//Or ThenByDescending
}
_testData = returnVal.ToList();
}
答案 1 :(得分:1)
你最好创建一个明确对每个属性进行比较的IComparer(因此你可以在其上有一个指定属性顺序的公共属性)。然后你可以只排序一次。
像这样的东西
public class DataComparer : Comparer<Data>
{
private readonly IList<string> _sortedProperties;
public DataComparer(IEnumerable<string> sortedProperties)
{
_sortedProperties = new List<string>(sortedProperties);
}
public override int Compare(Data x, Data y)
{
int result = 0;
foreach (var property in _sortedProperties)
{
if (property == "Name")
{
result = String.Compare(x.Name, y.Name, StringComparison.Ordinal);
}
else if (property == "Age")
{
result = x.Age.CompareTo(y.Age);
}
// Do other comparisons here
if (result != 0)
return result;
}
return 0;
}
}
此实现将使用给定的属性集合创建DataComparer,这些属性充当需要比较的属性。然后,Compare()将以所需的排序顺序遍历属性,直到找到不匹配的比较并返回。
最终结果将是更快的排序操作,输出类似
的内容// "Jim Frost" 13
// "Jim Frost" 24
// "Jim Smith" 11
我们首先要对Name
属性进行排序,然后是Age
等。
修改强>
你可以这样排序,
_testData.Sort(new DataComparer(sortCols));