簡體   English   中英

如何根據某些條件從列表中刪除項目

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

我有一個對象列表,列表中的每個對象都具有以下屬性:

  • 文檔名稱,
  • SwVersion,
  • ControllerSN,
  • FirstDoseTime,
  • EvtTime,
  • evt
  • 輸出

首先,我需要找到所有其FirstDoseTime屬性設置為特定值(1/1/1,12:00:00)的對象。 我們將這些稱為blankFirstDose對象。

然后,我需要在列表中進行搜索,以查看列表中是否存在每個對象對象,除了FirstDoseTime屬性(1/1/1/12以外的其他值),該列表中是否有與blankFirstDose對象完全相同的屬性。 :00:00)和FileName屬性。

最后,我要從列表中刪除所有blankFirstDose對象,這些對象在列表中具有對應的對象,該對象具有不同的FileName和FirstDoseTime,該對象不是1/1/1,12:00:00。

這是我這樣做的第一步。 該嘗試成功完成,但是當我擁有大量這些對象時,花費的時間太長。 我需要更高效,更快的東西。 謝謝你的幫助!

編輯:分析

我對“典型”案例進行了一些系統概要分析,以幫助您進行討論。 在這種情況下,AllEvents列表包含40,928個LogFileEvent項目,而blankFirstDoseLst包含12,092個項目。

在我的系統上完成所有這些操作所需的時間大約為16秒。 這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));

您可以利用HashSet保留應刪除的空白。

var blanksToRemove = new HashSet<LogFileEvent>();

然后Contains

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

將是O(1)操作,從而避免了在使用List時必須進行線性搜索的情況。 如果使用列表,則Contains的時間復雜度約為O(n),其中n是列表中的項目數。

更新資料

您可以進行的另一項更改如下。 既然你要

...以搜索列表,查看列表中是否有每個對象對象,除了FirstDoseTime屬性(1/1/1,12以外的其他值),該列表中是否存在與blankFirstDose對象完全相同的屬性: 00:00)和FileName屬性。

您可以消除第一個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);
        }
    }
}

這樣做你會避免遍歷中的項目blankFirstDoseLst的項目AllEvents有作為FirstDoseTime比你正在尋找的值不同。

感謝您收到的所有回復。 我最終使用了帶有自定義IEqualityComparer的哈希集策略,類似於@ZdeněkJelínek提到的內容。 自定義IEqualityComparer實現了我以前在“ if”語句中所做的檢查。

這將處理時間從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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM