[英]Remove duplicates from a List<T> based on a condition in C#
I have a List of an object (exobject in the below code sample) who each have SomeId, AnotherId, SomeOtherId and Timestamp. 我有一个对象的列表(在下面的代码示例中为exobject),每个对象都有SomeId,AnotherId,SomeOtherId和Timestamp。 This list might have duplicate entries with each record having a different Timestamp.
此列表可能有重复的条目,每个记录的时间戳都不同。 I want to remove all duplicates of this object with older Timestamps and only keep those that are the latest.
我想删除带有较旧时间戳的该对象的所有重复项,而仅保留最新的那些。
Sample object: 样本对象:
SomeId AnotherId SomeOtherId Timestamp
1 2 1 10
1 2 1 20
1 3 2 30
2 3 4 40
1 3 2 50
My required list should be 我需要的清单应该是
1,2,1,20 and 1,3,2,50 and 2,3,4,40.
I have a very crude implementation in C# do do this. 我在C#中有一个非常粗糙的实现来做到这一点。
for (int i = 0; i < exObject.Count - 1; i++)
{
for (int j = i + 1; j < exObject.Count - 1; j++)
{
if (exObject[i].SomeId == exObject[j].SomeId && exObject[i].AnotherId == exObject[j].AnotherId && exObject[i].SomeOtherId == exObject[j].SomeOtherId)
{
if (exObject[i].TimeStamp < exObject[j].TimeStamp)
exObject[i].TimeStamp = exObject[j].TimeStamp;
exObject.Remove(exObject[j]);
}
}
}
I would like to know if there is a more elegant and nicer way to do this or if there is a lambda I can use to accomplish this. 我想知道是否有更优雅,更好的方法来执行此操作,或者是否可以使用lambda来完成此操作。
You can Group By the 3 fields and take the first one of each group: 您可以按3个字段分组并采用每个分组的第一个:
List
.GroupBy(x=> new {x.prop1, x.prop2, x.prop3 })
.Select(g=> g.OrderByDescending(o=> o.dateprop).First())
.ToList();
Sample that is working perfectly: 运行良好的示例:
static void Main(string[] args)
{
List<Foo> myList = new List<Foo>();
myList.Add(new Foo(1, 2, 1, 10));
myList.Add(new Foo(1, 2, 1, 20));
myList.Add(new Foo(1, 3, 2, 30));
myList.Add(new Foo(2, 3, 4, 40));
myList.Add(new Foo(1, 3, 2, 50));
// The following returns 3 results with 20, 50 and 40 timeStamps.
var results = myList.GroupBy(x => new { x.SomeId, x.AnotherId, x.SomeOtherId })
.Select(g => g.OrderByDescending(o => o.Timestamp).First()).ToList();
}
System.Linq has a Distinct method. System.Linq有一个Distinct方法。 You'd have to implement an IEqualityComparer.
您必须实现IEqualityComparer。 Details of how here...
详细说明...
https://msdn.microsoft.com/en-us/library/bb338049(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/bb338049(v=vs.110).aspx
Edit based on your comment: If you do an orderBy it should keep the one you want... here's some code... 根据您的评论进行编辑:如果您执行了一项订单,它应该保留您想要的订单...这是一些代码...
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var data = new[]
{
new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 10 },
new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 20 }, // Duplicate
new SomeClass { SomeId = 1, AnotherId = 2, SomeOtherId = 2, Timestamp = 30 },
new SomeClass { SomeId = 1, AnotherId = 2, SomeOtherId = 2, Timestamp = 35 }, // Duplicate
new SomeClass { SomeId = 2, AnotherId = 4, SomeOtherId = 4, Timestamp = 40 },
new SomeClass { SomeId = 3, AnotherId = 2, SomeOtherId = 2, Timestamp = 50 },
new SomeClass { SomeId = 1, AnotherId = 1, SomeOtherId = 1, Timestamp = 50 } // Duplicate
};
var distinctList = data
.OrderBy(x => x.Timestamp)
.Distinct(new SomeClassComparer())
.ToList();
}
public class SomeClass
{
public int SomeId { get; set; }
public int AnotherId { get; set; }
public int SomeOtherId { get; set; }
public int Timestamp { get; set; }
}
public class SomeClassComparer : IEqualityComparer<SomeClass>
{
public bool Equals(SomeClass x, SomeClass y)
{
if (ReferenceEquals(x, y))
{
return true;
}
//Check whether any of the compared objects is null.
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
{
return false;
}
//Check whether the SomeClass's properties are equal.
return x.SomeId == y.SomeId &&
x.AnotherId == y.AnotherId &&
x.SomeOtherId == y.SomeOtherId;
}
public int GetHashCode(SomeClass someClass)
{
//Check whether the object is null
if (ReferenceEquals(someClass, null))
{
return 0;
}
//Get hash code for the fields
var hashSomeId = someClass.SomeId.GetHashCode();
var hashAnotherId = someClass.AnotherId.GetHashCode();
var hashSomeOtherId = someClass.SomeOtherId.GetHashCode();
//Calculate the hash code for the SomeClass.
return (hashSomeId ^ hashAnotherId) ^ hashSomeOtherId;
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.