我有一个对象列表,其结构与此类似: Id,OperationId,Prop1,Prop2,...
我必须从列表中删除所有具有相同Id但具有OperationId的Max值的对象。 例如,我有这个列表的实例:
new List<MyObject>
{
new MyObject() { Id = 1, OperationId = 1, Prop1, Prop2, ... },
new MyObject() { Id = 1, OperationId = 2, Prop1, Prop2, ... },
new MyObject() { Id = 2, OperationId = 1, Prop1, Prop2, ... },
new MyObject() { Id = 2, OperationId = 2, Prop1, Prop2, ... },
new MyObject() { Id = 3, OperationId = 2, Prop1, Prop2, ... }
}
结果必须是:
new List<MyObject>
{
new MyObject() { Id = 1, OperationId = 1, Prop1, Prop2, ... },
new MyObject() { Id = 2, OperationId = 1, Prop1, Prop2, ... },
new MyObject() { Id = 3, OperationId = 2, Prop1, Prop2, ... }
}
重要的是:我不必只找到Id和operationId ..结果必须是整个对象!
我尝试过使用Comparer,lambda表达式,Distinct,Grouping和Select,但我还没有找到解决方案......
我该如何解决?
感谢名单, 西蒙娜
答案 0 :(得分:1)
按Id分组对象,然后从每个组中选择仅具有最大OperationId的对象。但请记住,如果组中只有一个OperationId值,则应返回所有这些对象(minOperationId check):
var result = from o in objects
group o by o.Id into g
let maxOperationId = g.Max(o => o.OperationId)
let minOperationId = g.Min(o => o.OperationId)
from o in g
where o.OperationId == minOperationId || o.OperationId != maxOperationId
select o;
输入
{ Id = 1, OperationId = 1 }
{ Id = 1, OperationId = 2 }
{ Id = 2, OperationId = 1 }
{ Id = 2, OperationId = 2 }
{ Id = 2, OperationId = 3 }
{ Id = 3, OperationId = 1 }
{ Id = 4, OperationId = 1 }
{ Id = 4, OperationId = 1 }
输出
{ Id = 1, OperationId = 1 }
{ Id = 2, OperationId = 1 }
{ Id = 2, OperationId = 2 }
{ Id = 3, OperationId = 1 }
{ Id = 4, OperationId = 1 }
{ Id = 4, OperationId = 1 }
答案 1 :(得分:1)
您可以使用此查询:
myObjects = myObjects
.Groupby(obj => obj.Id)
.Select(grp => grp.OrderBy(obj => obj.OperationId).First())
.ToList();
根据ID删除所有重复项,只剩下最低的OperationId。
答案 2 :(得分:0)
假设您的对象类似于:
.rating-item{
border-width:3px;
border-color:black;
font-size:150%;
font-style:bold;
}
.rating-item span{
border-width: 2px;
padding:5.5px;
width:30px;
border-style: solid;
border-radius: 50%;
}
<div class="article-survey-container ">
<div class="article-survey ">
<div class="selected-text"></div>
<div class="recorded-message"></div>
<ul class="ratings">
<li data-rating="5" class="rating-item" id="muy-dificil-rating"> <span class="fontelico-emo-unhappy "> </span></li>
<li data-rating="4" class="rating-item" id="dificil-rating"> <span class="fontelico-emo-displeased"> </span></li>
<li data-rating="3" class="rating-item"id="normal-rating"> <span class="fontelico-emo-sleep"> </span></li>
<li data-rating="2" class="rating-item"id="facil-rating"> <span class="fontelico-emo-happy"> </span></li>
<li data-rating="1" class="rating-item" id="muy-facil-rating"> <span class="fontelico-emo-grin"> </span></span></li>
</ul>
<br>
<input type="hidden" name="dificultad" id="dificultad" value="">
</div>
</div>
</div>
我们可以使用以下LINQ查询:
public class MyObject
{
public Int32 Id
{
get;
set;
}
public Int32 OperationId
{
get;
set;
}
public override string ToString()
{
return String.Format("{0}-{1}", this.Id, this.OperationId);
}
}
以下是用法:
public static IEnumerable<MyObject> RemoveMaxOpIdInIdGroup(List<MyObject> items)
{
var result = items
// Group by id
.GroupBy(item =>
item.Id)
// Select each group and max operation id in each group
.Select(group =>
new { group, maxOperationId = group.Max(item => item.OperationId) })
// From each group select the item where opid is not max for this
// group or if the group has only one item
.SelectMany(groupWithMax =>
groupWithMax
.group
.Where(item =>
(item.OperationId != groupWithMax.maxOperationId) ||
(groupWithMax.group.Count() == 1)));
return result;
}
答案 3 :(得分:0)
如果您使用MaxBy
扩展方法such as the one written by Jon Skeet,则解决方案变得相当简单:
var result = items.GroupBy(item => item.Id).Select(x => x.MaxBy(y => y.OperationId));
(注意,对于具有Id和OperationId的多个项目,选择最大一个项目是任意的。)
示例程序:
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
namespace ConsoleApplication2
{
class MyObject
{
public int Id;
public int OperationId;
}
static class Program
{
[STAThread]
private static void Main()
{
IEnumerable<MyObject> items =
new List<MyObject>
{
new MyObject{Id = 1, OperationId = 1},
new MyObject{Id = 1, OperationId = 2},
new MyObject{Id = 2, OperationId = 1},
new MyObject{Id = 2, OperationId = 2},
new MyObject{Id = 3, OperationId = 2}
};
var result = items.GroupBy(item => item.Id).Select(x => x.MaxBy(y => y.OperationId));
}
}
public static class EnumerableMaxMinExt
{
public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
{
return source.MaxBy(selector, Comparer<TKey>.Default);
}
public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IComparer<TKey> comparer)
{
using (IEnumerator<TSource> sourceIterator = source.GetEnumerator())
{
if (!sourceIterator.MoveNext())
{
throw new InvalidOperationException("Sequence was empty");
}
TSource max = sourceIterator.Current;
TKey maxKey = selector(max);
while (sourceIterator.MoveNext())
{
TSource candidate = sourceIterator.Current;
TKey candidateProjected = selector(candidate);
if (comparer.Compare(candidateProjected, maxKey) > 0)
{
max = candidate;
maxKey = candidateProjected;
}
}
return max;
}
}
}
}