简体   繁体   English

检查列表是否包含一个属性相同的对象的优雅方法,并且仅在另一个属性的日期更晚时才替换

[英]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.

相关问题 C# - 检查列表是否包含属性等于值的对象? - C# - check if list contains an object where a property equals value? Linq,其中实体属性包含另一个列表 - Linq, where entity property contains another list 如何以整洁的方式检查collection是否包含一个属性等于传递给Contains方法的对象的对象? - How to check in neat way if collection contains an object which's one property is equal to the object passed to Contains method? C# Linq 在比较一个属性时检查列表是否包含所有其他列表项 - C# Linq check if a list contains all of another lists items when comparing on one property Linq方法来检查一个集合的属性与另一个集合的属性 - Linq way to check a property of one set against a property of another set 读取对象的子属性的优雅方式 - Elegant way of reading a child property of an object C# 检查属性是否为 null 的优雅方式 - C# elegant way to check if a property's property is null 在C#中,如何检查List &lt;&gt;中对象的属性是否包含字符串? - In C#, how to check if a property of an object in a List<> contains a string? 如何从列表中检索项目 <T> 其中一个属性恰好包含另一个列表中的单词? - How do I retrieve items from a List<T> where one property contains exactly the words from another list? 检查List1是否包含等于另一个List2的属性值的属性值 - Check List1 if it contains property value equal to property value of Another List2
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM