简体   繁体   English

如何根据某些条件从列表中删除项目

[英]How to remove items from a list based upon certain conditions

I have a list of objects and each object in the list has the following properties: 我有一个对象列表,列表中的每个对象都具有以下属性:

  • FileName, 文档名称,
  • SwVersion, SwVersion,
  • ControllerSN, ControllerSN,
  • FirstDoseTime, FirstDoseTime,
  • EvtTime, EvtTime,
  • Evt, evt
  • EvtOutput 输出

First I need to find all of the objects that have their FirstDoseTime property set to a specific value (1/1/1, 12:00:00). 首先,我需要找到所有其FirstDoseTime属性设置为特定值(1/1/1,12:00:00)的对象。 Let's call these blankFirstDose objects. 我们将这些称为blankFirstDose对象。

Then, I need to search through the list and see if for each blankFirstDose object, there is another object in the list that has the same exact properties as the blankFirstDose object except for the FirstDoseTime property (anything other than 1/1/1, 12:00:00) and the FileName property. 然后,我需要在列表中进行搜索,以查看列表中是否存在每个对象对象,除了FirstDoseTime属性(1/1/1/12以外的其他值),该列表中是否有与blankFirstDose对象完全相同的属性。 :00:00)和FileName属性。

Finally, I want to remove any blankFirstDose objects from the list that have a corresponding object in the list that has a different FileName and a FirstDoseTime that is something other than 1/1/1, 12:00:00. 最后,我要从列表中删除所有blankFirstDose对象,这些对象在列表中具有对应的对象,该对象具有不同的FileName和FirstDoseTime,该对象不是1/1/1,12:00:00。

Here is my first pass at doing so. 这是我这样做的第一步。 This attempt works successfully, but takes far too long when I have a large list of these objects. 该尝试成功完成,但是当我拥有大量这些对象时,花费的时间太长。 I need something that is more efficient and much faster. 我需要更高效,更快的东西。 Thanks for your help! 谢谢你的帮助!

EDIT: Profiling 编辑:分析

I performed some system profiling for a "typical" case to help inform this discussion. 我对“典型”案例进行了一些系统概要分析,以帮助您进行讨论。 In this case, the AllEvents list contains 40,928 LogFileEvent items and the blankFirstDoseLst contains 12,092 items. 在这种情况下,AllEvents列表包含40,928个LogFileEvent项目,而blankFirstDoseLst包含12,092个项目。

The amount of time it takes to complete all of these operations on my system is approximately 16 seconds. 在我的系统上完成所有这些操作所需的时间大约为16秒。 Almost all of those 16 seconds are spent in the two foreach loops. 这16秒几乎全部用在两个foreach循环中。

var blankFirstDoseLst = 
    AllEvents.GroupBy(e => e.FirstDoseTime)
             .Where(g => g.FirstOrDefault().FirstDoseTime == PatientModel.DEFAULT_DATE)
             .SelectMany(g => g)
             .ToList();
List<LogFileEvent> blanksToRemove = new List<LogFileEvent>();
foreach (var evt in AllEvents)
{
    foreach (var blankEvt in blankFirstDoseLst)
    {
        if ((evt.FileName      != blankEvt.FileName) &&
            (evt.SwVersion     == blankEvt.SwVersion) &&
            (evt.ControllerSN  == blankEvt.ControllerSN) &&
            (evt.FirstDoseTime != blankEvt.FirstDoseTime) &&
            (evt.EvtTime       == blankEvt.EvtTime) &&
            (evt.Evt           == blankEvt.Evt) &&
            (evt.EvtOutput     == blankEvt.EvtOutput))
        {
            blanksToRemove.Add(blankEvt);
        }
    }
}

// Remove any duplicates ignoring first dose date and time
AllEvents.RemoveAll(e => blanksToRemove.Contains(e));

You could make use of a HashSet for keeping the blanks that should be removed. 您可以利用HashSet保留应删除的空白。

var blanksToRemove = new HashSet<LogFileEvent>();

Then the Contains 然后Contains

AllEvents.RemoveAll(e => blanksToRemove.Contains(e));

would be an O(1) operation, avoiding the linear search that it has to be done, when you use a List. 将是O(1)操作,从而避免了在使用List时必须进行线性搜索的情况。 In case of using a list the time complexity of Contains it is of the order of O(n), where n is the number of items in your list. 如果使用列表,则Contains的时间复杂度约为O(n),其中n是列表中的项目数。

Update 更新资料

Another change that you could make it is the following. 您可以进行的另一项更改如下。 Since you want 既然你要

...to search through the list and see if for each blankFirstDose object, there is another object in the list that has the same exact properties as the blankFirstDose object except for the FirstDoseTime property (anything other than 1/1/1, 12:00:00) and the FileName property. ...以搜索列表,查看列表中是否有每个对象对象,除了FirstDoseTime属性(1/1/1,12以外的其他值),该列表中是否存在与blankFirstDose对象完全相同的属性: 00:00)和FileName属性。

You could eliminate the items of the first foreach statement as below: 您可以消除第一个foreach语句的项,如下所示:

foreach (var evt in AllEvents.Where(evt=>evt.FirstDoseTime != PatientModel.DEFAULT_DATE))
{
    foreach (var blankEvt in blankFirstDoseLst)
    {
        if ((evt.FileName      != blankEvt.FileName) &&
            (evt.SwVersion     == blankEvt.SwVersion) &&
            (evt.ControllerSN  == blankEvt.ControllerSN) &&
            (evt.EvtTime       == blankEvt.EvtTime) &&
            (evt.Evt           == blankEvt.Evt) &&
            (evt.EvtOutput     == blankEvt.EvtOutput))
        {
            blanksToRemove.Add(blankEvt);
        }
    }
}

Doing so you will avoid to loop through the items in blankFirstDoseLst for the items AllEvents that have as a FirstDoseTime a different than the value you are looking for. 这样做你会避免遍历中的项目blankFirstDoseLst的项目AllEvents有作为FirstDoseTime比你正在寻找的值不同。

Thank you for all the responses I received. 感谢您收到的所有回复。 I ended up using a hashset strategy with a custom IEqualityComparer similar to what @ZdeněkJelínek mentioned. 我最终使用了带有自定义IEqualityComparer的哈希集策略,类似于@ZdeněkJelínek提到的内容。 The custom IEqualityComparer implements the checks I was previously doing in the "if" statement. 自定义IEqualityComparer实现了我以前在“ if”语句中所做的检查。

This has significantly reduced the amount of processing time down from 16s to about 1s. 这将处理时间从16s大大减少到了1s。

            // Remove any events with blank first dose time if there is a duplicate that has
            // a valid first dose time
            var blanksToRemove        = new List<LogFileEvent>();
            var blankFirstDoseEvts    = AllEvents.Where(e => e.FirstDoseTime == PatientModel.DEFAULT_DATE)
                                                 .ToList();
            var nonBlankFirstDoseEvts = new HashSet<LogFileEvent>(AllEvents.Where(e => e.FirstDoseTime != PatientModel.DEFAULT_DATE),
                                                                  new BlankFirstDoseComparer());

            foreach (var blankEvt in blankFirstDoseEvts)
            {
                if (nonBlankFirstDoseEvts.Contains(blankEvt))
                {
                    blanksToRemove.Add(blankEvt);
                }
            }

            AllEvents.RemoveAll(e => blanksToRemove.Contains(e));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何根据多个条件并使用linq从通用列表中删除项目 - How do I remove items from generic list, based on multiple conditions and using linq c# lambda 表达式根据不同列表中的给定条件从列表中删除项目 - c# lambda expression to remove items from a list based on given conditions in a different list 如何遍历字符串项列表并根据某些条件插入另一个字符串项? - How to traverse a list of string items and insert another string item(s) based on certain conditions? 使用LINQ根据条件从列表中删除 - USe LINQ to remove from a list based on conditions 如何根据随机条件从二维数组中删除项目? - How do I remove items from a 2-d array based on randomised conditions? 如何“Assert.That()”列表中的项目与 NUnit 匹配某些条件? - How to "Assert.That()" Items in a List match certain conditions with NUnit? 如何根据库存的可用性自动从 ASP.NET 中的下拉列表中删除元素? - How to remove the elements from the drop down list in ASP.NET automatically based upon the availability of the stock? LINQ:根据两个列表的属性进行比较,并返回符合特定条件的项目 - LINQ: Compare two list based on their properties and return items that match certain conditions 根据特定属性从列表中选择并显示某些项目 - Selecting and displaying certain items from list based on specific property 使用LINQ根据日期从列表中删除项目 - use LINQ to remove items from a list based on a date
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM