簡體   English   中英

Linq查詢按字段1分組,對字段2計數並按連接集合的值之間的計數過濾

[英]Linq query to group by field1, count field2 and filter by count between values of joined collection

我在正確設置linq查詢時遇到問題。 我一直拒絕使用foreach循環來這樣做,因為我試圖更好地理解linq。

我在LinqPad中有以下數據。

void Main()
{
    var events = new[] {
        new {ID = 1, EventLevel = 1, PatientID = "1", CodeID = "2", Occurences = 0 },
        new {ID = 2, EventLevel = 2, PatientID = "1", CodeID = "2", Occurences = 0 },
        new {ID = 3, EventLevel = 1, PatientID = "2", CodeID = "1", Occurences = 0 },
        new {ID = 4, EventLevel = 3, PatientID = "2", CodeID = "2", Occurences = 0 },
        new {ID = 5, EventLevel = 1, PatientID = "3", CodeID = "3", Occurences = 0 },
        new {ID = 6, EventLevel = 3, PatientID = "1", CodeID = "4", Occurences = 0 }
    };

    var filter = new FilterCriterion();
    var searches = new List<FilterCriterion.Occurence>();
    searches.Add(new FilterCriterion.Occurence() { CodeID = "1", MinOccurences = 2, MaxOccurences = 3 });
    searches.Add(new FilterCriterion.Occurence() { CodeID = "2", MinOccurences = 2, MaxOccurences = 3 });

    filter.Searches = searches;

    var summary = from e in events
        let de = new
        {
            PatientID = e.PatientID,
            CodeID = e.CodeID
        }
        group e by de into t
        select new
        {
            PatientID = t.Key.PatientID,
                CodeID = t.Key.CodeID,
            Occurences = t.Count(d => t.Key.CodeID == d.CodeID)
        };

    var allCodes = filter.Searches.Select(i => i.CodeID);

    summary = summary.Where(e => allCodes.Contains(e.CodeID));

    // How do I find the original ID property from the "events" collection and how do I 
    // eliminate the instances where the Occurences is not between MinOccurences and MaxOccurences.

    foreach (var item in summary)
        Console.WriteLine(item);
}

public class FilterCriterion
{

   public IEnumerable<Occurence> Searches { get; set; }

   public class Occurence
   {
       public string CodeID { get; set; }
       public int? MinOccurences { get; set; }
       public int? MaxOccurences { get; set; }
   }

}

我的問題是需要通過MinOccurences和MaxOccurences過濾器屬性過濾結果,最后我想要ID為1,2、3和4的“事件”對象。

預先感謝您能提供幫助。

要在處理結束時訪問event.ID ,您需要在第一個查詢中傳遞它。 更改select為此:

// ...
group e by de into t
select new
{
    PatientID = t.Key.PatientID,
    CodeID = t.Key.CodeID,
    Occurences = t.Count(d => t.Key.CodeID == d.CodeID),
    // taking original items with us
    Items = t
};

完成之后,您的最終查詢(包括事件過濾器) 可能如下所示:

var result = summary
    // get all necessary data, including filter that matched given item
    .Select(Item => new
        {
            Item,
            Filter = searches.FirstOrDefault(f => f.CodeID == Item.CodeID)
        })
    // get rid of those without matching filter
    .Where(i => i.Filter != null)
    // this is your occurrences filtering
    .Where(i => i.Item.Occurences >= i.Filter.MinOccurences
        && i.Item.Occurences <= i.Filter.MaxOccurences)
    // and finally extract original events IDs
    .SelectMany(i => i.Item.Items)
    .Select(i => i.ID);

這產生12作為結果。 34被忽略了,因為它們沒有過去的事件過濾。

我已經在linqpad中運行了您的程序。

我的理解是,您想使用filter.MinOccurences和filter.MaxOccurences對結果數據集的出現次數進行過濾。

您可以使用Where子句添加其他過濾器。

if (filter.MinOccurences.HasValue)
 summary = summary.Where (x=> x.Occurences >= filter.MinOccurences);

if (filter.MaxOccurences.HasValue)
 summary = summary.Where (x=> x.Occurences <= filter.MaxOccurences);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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