我有一个对象列表(以下代码示例中为exobject),每个对象都有SomeId,AnotherId,SomeOtherId和Timestamp。此列表可能具有重复条目,每条记录具有不同的时间戳。 我希望使用较旧的时间戳删除此对象的所有重复项,并仅保留最新的那些。
示例对象:
SomeId AnotherId SomeOtherId Timestamp
1 2 1 10
1 2 1 20
1 3 2 30
2 3 4 40
1 3 2 50
我需要的清单应该是
1,2,1,20 and 1,3,2,50 and 2,3,4,40.
我在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]);
}
}
}
我想知道是否有更优雅和更好的方法来做这个或者如果有一个lambda我可以用它来完成这个。
答案 0 :(得分:1)
您可以按3个字段进行分组并获取每个组中的第一个:
List
.GroupBy(x=> new {x.prop1, x.prop2, x.prop3 })
.Select(g=> g.OrderByDescending(o=> o.dateprop).First())
.ToList();
完美运作的示例:
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();
}
答案 1 :(得分:1)
System.Linq有一个Distinct方法。您必须实现IEqualityComparer。详情如何......
https://msdn.microsoft.com/en-us/library/bb338049(v=vs.110).aspx
根据你的评论进行编辑:如果你做了一个订单它应该保留你想要的那个......这里有一些代码...
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;
}
}
}
}