[英]Elegant way to check if a list contains an object where one property is the same, and replace only if the date of another property is later
I have a class as follows : 我有一个课程如下:
Object1{
int id;
DateTime time;
}
I have a list of Object1
. 我有一个
Object1
列表。 I want to cycle through another list of Object1
, search for an Object1
with the same ID and replace it in the first list if the time value is later than the time value in the list. 我想遍历另一个
Object1
列表,搜索具有相同ID的Object1
,如果时间值晚于列表中的时间值,则将其替换为第一个列表。 If the item is not in the first list, then add it. 如果该项目不在第一个列表中,则添加该项目。
I'm sure there is an elegant way to do this, perhaps using linq? 我确信有一种优雅的方式可以做到这一点,也许使用linq? :
:
List<Object1> listOfNewestItems = new List<Object1>();
List<Object1> listToCycleThrough = MethodToReturnList();
foreach(Object1 object in listToCycleThrough){
if(listOfNewestItems.Contains(//object1 with same id as object))
{
//check date, replace if time property is > existing time property
} else {
listOfNewestItems.Add(object)
}
Obviously this is very messy (and that's without even doing the check of properties which is messier again...), is there a cleaner way to do this? 显然这是非常混乱的(而且甚至没有检查再次变得更加混乱的属性......),有没有更清洁的方法来做到这一点?
var finalList = list1.Concat(list2)
.GroupBy(x => x.id)
.Select(x => x.OrderByDescending(y=>y.time).First())
.ToList();
here is the full code to test 这是要测试的完整代码
public class Object1
{
public int id;
public DateTime time;
}
List<Object1> list1 = new List<Object1>()
{
new Object1(){id=1,time=new DateTime(1991,1,1)},
new Object1(){id=2,time=new DateTime(1992,1,1)}
};
List<Object1> list2 = new List<Object1>()
{
new Object1(){id=1,time=new DateTime(2001,1,1)},
new Object1(){id=3,time=new DateTime(1993,1,1)}
};
and OUTPUT: 和输出:
1 01.01.2001
2 01.01.1992
3 01.01.1993
This is how to check: 这是如何检查:
foreach(var object in listToCycleThrough)
{
var currentObject = listOfNewestItems
.SingleOrDefault(obj => obj.Id == object.Id);
if(currentObject != null)
{
if (currentObject.Time < object.Time)
currentObject.Time = object.Time
}
else
listOfNewestItems.Add(object)
}
But if you have large data, would be suggested to use Dictionary
in newest list, time to look up will be O(1) instead of O(n) 但是如果你有大量数据,建议在最新列表中使用
Dictionary
,那么查找的时间将是O(1)而不是O(n)
You can use LINQ. 您可以使用LINQ。
Enumerable.Except
to get the set difference(the newest), and join
to find the newer objects. Enumerable.Except
获取设置差异(最新),并join
以查找较新的对象。
var listOfNewestIDs = listOfNewestItems.Select(o => o.id);
var listToCycleIDs = listToCycleThrough.Select(o => o.id);
var newestIDs = listOfNewestIDs.Except(listToCycleIDs);
var newestObjects = from obj in listOfNewestItems
join objID in newestIDs on obj.id equals objID
select obj;
var updateObjects = from newObj in listOfNewestItems
join oldObj in listToCycleThrough on newObj.id equals oldObj.id
where newObj.time > oldObj.time
select new { oldObj, newObj };
foreach (var updObject in updateObjects)
updObject.oldObj.time = updObject.newObj.time;
listToCycleThrough.AddRange(newestObjects);
Note that you need to add using System.Linq;
请注意,您需要
using System.Linq;
添加using System.Linq;
. 。
Here's a demo: http://ideone.com/2ASli 这是一个演示: http : //ideone.com/2ASli
I'd create a Dictionary
to lookup the index for an Id
and use that 我创建一个
Dictionary
来查找Id
的索引并使用它
var newItems = new List<Object1> { ...
IList<Object1> itemsToUpdate = ...
var lookup = itemsToUpdate.
Select((i, o) => new { Key = o.id, Value = i }).
ToDictionary(i => i.Key, i => i.Value);
foreach (var newItem in newitems)
{
if (lookup.ContainsKey(newitem.ID))
{
var i = lookup[newItem.Id];
if (newItem.time > itemsToUpdate[i].time)
{
itemsToUpdate[i] = newItem;
}
}
else
{
itemsToUpdate.Add(newItem)
}
}
That way, you wouldn't need to reenumerate the list for each new item, you'd benefit for the hash lookup performance. 这样,您就不需要重新枚举每个新项目的列表,您将受益于哈希查找性能。
This should work however many times an Id
is repeated in the list of new items. 这应该可以工作很多次,在新项目列表中重复
Id
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.