简体   繁体   中英

c# LINQ filter nested collection

I have the next class hierarchy:

public class URecordFieldEmr
{
   public Guid Key { get; set; }
   public string Alias { get; set; }
   public List<Value> Values { get; set; }
}

public class Value
{
    public int Index { get; set; }
    public List<DayOfWeek> DaysOfWeek { get; set; } 
}

I need to filter List<URecordFieldEmr> by day of week, so I'm trying like this:

var filtredExercises = uRecordFields
                         .Where(f => f.Values.Any(v => v.DaysOfWeek.Contains(dayOfWeek)))
                         .ToList();

But in this case if I have two Value s: first value - DaysOfWeek - sunday, second value - monday, and when I'm trying filtering by sunday I get both these values. But I need values that contains specific day of week.

PS dayOfWeek is .NET enum

The Question is, why do you even have a List of dayofweek in class values if the match can only be exaclty one day week? Shouldn't value then just look like this?

public class Value
{
    public int Index { get; set; }
    public DayOfWeek d { get; set; } 
}

Or do you wannt to be able also to check if List<DayOfWeek> DaysOfWeek contains the exact same combination as you want to compare to, for example Monday and Sunday, then the list needs to contain exactly and only Monday and sunday? Or Wednesday and Friday and Thurstday then the list only must contain these values and all 3 need to be present?

Anyhow, in case of that you only need to compare one entry and it should be the only entry in the list (as you described it), either rewrite the values class as described above. Or you could check it like this:

var filtredExercises = uRecordFields
                         .Where(f => f.Values.Any( v => v.DaysOfWeek.count = 1 && v.DaysOfWeek.FirstOrDefault() == dayofweek))
                         .ToList();

Maybe this approach is more readable. You also could add distinct() before firstordefault() if your class allowes multiple entries of the same day.

You also could do a method on the class values that does the check for you and then you call that method in the lambda. But this depends if the natural responsibility for the check is in the class itself.

What I assume is, you need to filter the matched Values property too right? If so the below query may help

var result = uRecordFields.Select(x => new URecordFieldEmr
{
    Values = x.Values.Where(y => y.DaysOfWeek.Any(z => z == DayOfWeek.Sunday)).ToList(),
    Alias = x.Alias,
    Key = x.Key
}).Where(x => x.Values != null && x.Values.Count != 0).ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM