处理排名数据w/C#&;林克
我在一个列表中有一个对象,我需要以几种不同的方式对其进行排序。目前,该代码相当笨拙,因为它需要我单独处理每一列。例如:处理排名数据w/C#&;林克,c#,linq,linq-to-objects,C#,Linq,Linq To Objects,我在一个列表中有一个对象,我需要以几种不同的方式对其进行排序。目前,该代码相当笨拙,因为它需要我单独处理每一列。例如: public class Data { public int AValue { get; set; } public int ARanking { get; set; } public int BValue { get; set; } public int BRanking { get; set; } public int CValue
public class Data
{
public int AValue { get; set; }
public int ARanking { get; set; }
public int BValue { get; set; }
public int BRanking { get; set; }
public int CValue { get; set; }
public int CRanking { get; set; }
}
public class Container
{
public List<Data> RankingData { get; set; }
public void RankData()
{
int count = 1;
foreach (Data item in RankingData.OrderBy(d => d.AValue))
{
item.ARanking = count;
count++;
}
count = 1;
foreach (Data item in RankingData.OrderBy(d => d.BValue))
{
item.BRanking = count;
count++;
}
count = 1;
foreach (Data item in RankingData.OrderBy(d => d.CValue))
{
item.CRanking = count;
count++;
}
}
}
公共类数据
{
公共整数AValue{get;set;}
public int ARanking{get;set;}
公共int BValue{get;set;}
公共整数{get;set;}
公共int值{get;set;}
公共int启动{get;set;}
}
公营货柜
{
公共列表排列数据{get;set;}
公共无效RankData()
{
整数计数=1;
foreach(RankingData.OrderBy(d=>d.AValue)中的数据项)
{
item.ARanking=计数;
计数++;
}
计数=1;
foreach(RankingData.OrderBy(d=>d.BValue)中的数据项)
{
item.BRanking=计数;
计数++;
}
计数=1;
foreach(RankingData.OrderBy(d=>d.CValue)中的数据项)
{
项目.盘车=计数;
计数++;
}
}
}
我试图解决的问题是,我想写一些大致如下的内容:
public void RankData<V, R>()
{
int count = 1;
foreach(Data item in RankingData.OrderBy(V))
{
item.R = count;
count++;
}
}
void SetRanking(this List<Data> dataSet, Func<Data,int> getOrderBy, Action<Data,int> setRank)
{
var ordered = dataSet.OrderBy(getOrderBy).ToArray();
int i = i;
foreach (Data item in ordered)
{
setRank(item, i);
i++;
}
}
RankingData.SetRanking(d => d.AValue, (d,i) => d.ARanking = i);
RankingData.SetRanking(d => d.BValue, (d,i) => d.BRanking = i);
RankingData.SetRanking(d => d.CValue, (d,i) => d.CRanking = i);
public void RankData()
{
整数计数=1;
foreach(RankingData.OrderBy(V)中的数据项)
{
项目R=计数;
计数++;
}
}
因此,当我需要更改排名逻辑(例如,处理打破平局的规则)时,我只编写一次代码,而不是复制代码20次,以使规则匹配。我错过了什么
更新
以Tanzelax的解决方案为基础,这是我提出的扩展类:
public static class RankingExtension
{
public static void SetRanking<TKey>(this List<Data> dataSet, bool Ascending, Func<Data, TKey> getOrderBy, Action<Data, int> setRank)
where TKey : IComparable
{
var ordered = (Ascending) ? dataSet.OrderBy(getOrderBy) : dataSet.OrderByDescending(getOrderBy);
int i = 1;
foreach (Data item in ordered)
{
setRank(item, i);
i++;
}
}
}
公共静态类扩展
{
公共静态void SetRanking(此列表数据集,bool升序,Func getOrderBy,Action setRank)
其中TKey:i可比较
{
var ordered=(升序)?dataSet.OrderBy(getOrderBy):dataSet.OrderByDescending(getOrderBy);
int i=1;
foreach(已订购的数据项)
{
setRank(第i项);
i++;
}
}
}
我必须添加一个开关,以便控制字段是否按升序排序。在我的测试场景中,它会产生适当的输出:
List<Data> test = new List<Data>();
test.Add(new Data { AValue = 25, BValue = 1.25, CValue = 99.99 });
test.Add(new Data { AValue = 89, BValue = 2.10, CValue = 1.01 });
test.Add(new Data { AValue = 10, BValue = 6, CValue = 45.45 });
test.Add(new Data { AValue = 15, BValue = 2.33, CValue = 2.99 });
test.Add(new Data { AValue = 90, BValue = 5.43, CValue = 27.89 });
test.SetRanking(false, d => d.AValue, (d, i) => d.ARank = i);
test.SetRanking(false, d => d.BValue, (d, i) => d.BRank = i);
test.SetRanking(true, d => d.CValue, (d, i) => d.CRank = i);
List test=newlist();
添加(新数据{AValue=25,BValue=1.25,CValue=99.99});
添加(新数据{AValue=89,BValue=2.10,CValue=1.01});
添加(新数据{AValue=10,BValue=6,CValue=45.45});
添加(新数据{AValue=15,BValue=2.33,CValue=2.99});
添加(新数据{AValue=90,BValue=5.43,CValue=27.89});
test.SetRanking(false,d=>d.AValue,(d,i)=>d.ARank=i);
test.SetRanking(false,d=>d.b值,(d,i)=>d.BRank=i);
test.SetRanking(真,d=>d.CValue,(d,i)=>d.CRank=i);
未测试,但类似以下内容:
public void RankData<V, R>()
{
int count = 1;
foreach(Data item in RankingData.OrderBy(V))
{
item.R = count;
count++;
}
}
void SetRanking(this List<Data> dataSet, Func<Data,int> getOrderBy, Action<Data,int> setRank)
{
var ordered = dataSet.OrderBy(getOrderBy).ToArray();
int i = i;
foreach (Data item in ordered)
{
setRank(item, i);
i++;
}
}
RankingData.SetRanking(d => d.AValue, (d,i) => d.ARanking = i);
RankingData.SetRanking(d => d.BValue, (d,i) => d.BRanking = i);
RankingData.SetRanking(d => d.CValue, (d,i) => d.CRanking = i);
void SetRanking(此列表数据集,Func getOrderBy,Action setRank)
{
var ordered=dataSet.OrderBy(getOrderBy.ToArray();
int i=i;
foreach(已订购的数据项)
{
setRank(第i项);
i++;
}
}
RankingData.SetRanking(d=>d.AValue,(d,i)=>d.ARanking=i);
RankingData.SetRanking(d=>d.b值,(d,i)=>d.BRanking=i);
RankingData.SetRanking(d=>d.CValue,(d,i)=>d.CRanking=i);
传入一个返回排名键的Func
。K应该实现IComparable
public static void Rank<K>( IEnumerable<Data> source, Func<Data,K> rankBy ) where K : IComparable
{
int count = 1;
foreach (var item in source.OrderBy( rankBy ))
{
item.R = count;
++count;
}
}
publicstaticvoidrank(IEnumerable源代码,Func rankBy),其中K:IComparable
{
整数计数=1;
foreach(source.OrderBy(rankBy)中的var项)
{
项目R=计数;
++计数;
}
}
这与Tanzelax的答案类似,但是一种通用的扩展方法
public static void RankData<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Action<TSource, int> rankSetter
)
{
int count = 1;
foreach (var item in source.OrderBy(keySelector))
{
rankSetter(item, count);
++count;
}
}
你的密码不太清楚,但它让我非常接近。我将在稍后发布我的修改。@thaBadDawg:很高兴我能帮上忙。:)也可以把数据之类的东西拿出来。另外,不需要传递升序布尔,只需传递orderBy lambda中的负CValue,尽管我相信很多人会反对这种方法。