Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"
以上list如果直接使用distinct方法進行過濾,仍然返回3條數據,而需要的結果是2條數據。下面給出解這個問題的方法:
方法1: Distinct 方法中使用的相等比較器。這個比較器需要重寫Equals和GetHashCode方法,個人不推薦,感覺較麻煩,需要些多余的類,並且用起來還要實例化一個比較器,當然自己也可以寫一個泛型的比較器生成工廠用來專門生成比較器,但仍然覺得較麻煩。
MSDN給出的做法,具體參照:http://msdn.microsoft.com/zh-cn/library/bb338049.aspx
方法2:自己擴展一個DistinctBy。這個擴展方法還是很不錯的,用起來很簡潔,適合為框架添加的Distinct擴展方法。
public static IEnumerable<TSource> DistinctBy<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
使用方法如下(針對ID,和Name進行Distinct):
var query = people.DistinctBy(p => new { p.Id, p.Name });
若僅僅針對ID進行distinct:
var query = people.DistinctBy(p => p.Id);
方法3:通過GroupBy分組后,並取出第一條數據。簡單易用,很方便。這是一種迂回策略,代碼理解起來沒有Distinct表意清晰,雖然實現了效果。
List<Person> distinctPeople = allPeople
.GroupBy(p => new {p.Id, p.Name} )
.Select(g => g.First())
.ToList();
//這個看起來很美好,但是綁定到gridview時則不顯示也不提示錯誤,采用下面的方法很可靠
ViewState["0964zt"] = "簡易報警"; //不顯示暫停
bool xswg = this.chk_xswg.Checked;//是否顯示完工
if (xswg)//顯示所有延期的記錄,按照ddid降序排列的1000條記錄
{
var cx_dd_bj = (from aa in sjklj.sc_ddxx
where aa.yq.HasValue && aa.yq.Value > 0 && ((aa.zt.HasValue && aa.zt == false) || aa.zt.HasValue == false)
orderby aa.ddid descending
select aa).Take(1000).GroupBy(bb => bb.ddid);
List<sc_ddxx> lst_jybq = new List<sc_ddxx>();
lst_jybq.Clear();
foreach(var kk in cx_dd_bj)
{
foreach(var gg in kk)
{
lst_jybq.Add(gg);//獲取了第一條記錄
break;
}
}
this.gv_scjh.DataSource = lst_jybq;
try
{
this.gv_scjh.PageIndex = 0;
}
catch(Exception err)
{
aspnetajaxjavascript.Msg(this.UpdatePanel1, err.Message, "2", "3000");
}
this.gv_scjh.DataBind();
}
else //不顯示完工的,即沒有完工的,就是【待定】
{
var cx_dd_bj = (from aa in sjklj.sc_ddxx
where aa.czzt == "待定" && aa.yq.HasValue && aa.yq.Value > 0 && ((aa.zt.HasValue && aa.zt == false) || aa.zt.HasValue == false)
orderby aa.ddid descending
select aa).Take(1000).GroupBy(bb => bb.ddid);
List<sc_ddxx> lst_jybq = new List<sc_ddxx>();
lst_jybq.Clear();
foreach (var kk in cx_dd_bj)
{
foreach (var gg in kk)
{
lst_jybq.Add(gg);//獲取了第一條記錄
break;
}
}
this.gv_scjh.DataSource = lst_jybq;
try
{
this.gv_scjh.PageIndex = 0;
}
catch (Exception err)
{
aspnetajaxjavascript.Msg(this.UpdatePanel1, err.Message, "2", "3000");
}
this.gv_scjh.DataBind();
}
Linq分組及排序,取前N條記錄
2016年05月18日 15:02:10
閱讀數:5199
Linq多字段分組排序並取前N條記錄時,一定要先分組再排序,不然取到的記錄是不規則的
代碼示例【按HotWord分組,並取sorNum倒序,取前15條記錄】
- [Route("api/XXX/getHotWord")]
- public HttpResponseMessage Post(WordModel model)
- {
- try
- {
- using (BZTEntities ctx = new BZTEntities())
- {
- var wflist = from u in ctx.T_HotWord
- where u.Type==model.type
- group u by new { HotWord = u.HotWord, sortNum = u.SortNum } into g
- select new { g.Key.HotWord, g.Key.sortNum };
- wflist = wflist.OrderByDescending(x => x.sortNum);
- var hotWord = wflist.ToList().Take(15).Select(a => a.HotWord).ToList();
- var Str = string.Join(",", hotWord);
- return Request.CreateResponse(HttpStatusCode.OK, new { errorCode = 1, hotWord = Str });
- }
- }
- catch (Exception ex)
- {
- Log.Error("獲取xxxxx失敗:" + ex.Message, ex);
- return Request.CreateResponse(HttpStatusCode.OK, new { errorCode = 2 });
- }
- }
- }
特別提醒:list對象綁定gridview時,如果用自帶的分頁事件綁定,則不能實現分頁,下面的代碼完美解決。
bool xswg = this.chk_xswg.Checked;//是否顯示完工
if (xswg)//顯示所有延期的記錄,按照ddid降序排列的1000條記錄
{
var cx_dd_bj = (from aa in sjklj.sc_ddxx
where aa.yq.HasValue && aa.yq.Value > 0 && ((aa.zt.HasValue && aa.zt == false) || aa.zt.HasValue == false)
orderby aa.ddid descending
select aa).Take(1000).GroupBy(bb => bb.ddid).OrderByDescending(cc => cc.Key)
.Select(dd => dd.FirstOrDefault());
this.gv_scjh.DataSource = cx_dd_bj;
this.gv_scjh.DataBind();
// FirstOrDefault()是解決意外錯誤的好方法,否則可能沒有數據顯示甚至沒有提示
/*
List<sc_ddxx> lst_jybq = new List<sc_ddxx>();
lst_jybq.Clear();
foreach(var kk in cx_dd_bj)
{
foreach(var gg in kk)
{
lst_jybq.Add(gg);//獲取了第一條記錄
break;
}
}
//用戶viewstate["datajybj"]記錄list數據
ViewState["datajybj"] = lst_jybq;
this.gv_scjh.DataSource = lst_jybq;
try
{
this.gv_scjh.PageIndex = 0;
}
catch(Exception err)
{
aspnetajaxjavascript.Msg(this.UpdatePanel1, err.Message, "2", "3000");
}
this.gv_scjh.DataBind();
*/
}
else //不顯示完工的,即沒有完工的,就是【待定】
{
var cx_dd_bj = (from aa in sjklj.sc_ddxx
where aa.czzt == "待定" && aa.yq.HasValue && aa.yq.Value > 0 && ((aa.zt.HasValue && aa.zt == false) || aa.zt.HasValue == false)
orderby aa.ddid descending
select aa).Take(1000).GroupBy(bb => bb.ddid).OrderByDescending(cc => cc.Key)
.Select(dd => dd.FirstOrDefault());
this.gv_scjh.DataSource = cx_dd_bj;
this.gv_scjh.DataBind();
return;
/*
List<sc_ddxx> lst_jybq = new List<sc_ddxx>();
lst_jybq.Clear();
foreach (var kk in cx_dd_bj)
{
foreach (var gg in kk)
{
lst_jybq.Add(gg);//獲取了第一條記錄
break;
}
}
//用戶viewstate["datajybj"]記錄list數據
ViewState["datajybj"] = lst_jybq;
this.gv_scjh.DataSource = lst_jybq;
try
{
this.gv_scjh.PageIndex = 0;
}
catch (Exception err)
{
aspnetajaxjavascript.Msg(this.UpdatePanel1, err.Message, "2", "3000");
}
this.gv_scjh.DataBind();
*/
}