[英]How do I remove items from generic list, based on multiple conditions and using linq
[英]How to remove items from a list based upon certain conditions
我有一個對象列表,列表中的每個對象都具有以下屬性:
首先,我需要找到所有其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.