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

北战南征 提交于 2019-12-12 01:59:09

问题


I'm having trouble with getting a my linq query correct. I've been resisting doing this with foreach loops because I'm trying to better understand linq.

I have following data in 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; }
   }

}

The problem I have is that need to filter the results by the MinOccurences and MaxOccurences filter property and in the end I want the "events" objects where the IDs are 1,2,3 and 4.

Thanks in advance if you can provide help.


回答1:


To access event.ID at the end of processing you need to pass it with your first query. Alter select to this:

// ...
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
};

Having done that, your final query (including occurrences filter) might look like this:

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);

This produces 1, 2 as result. 3 and 4 are left out as they don't get past occurrences filtering.




回答2:


I have run your program in linqpad.

My understanding is that you want to filter using filter.MinOccurences and filter.MaxOccurences on Occurences count of result data set.

You can add additional filters using Where clause.

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

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


来源:https://stackoverflow.com/questions/14061718/linq-query-to-group-by-field1-count-field2-and-filter-by-count-between-values-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!