Mikhail Kostiuchenko
Mikhail Kostiuchenko

Reputation: 10461

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 Values: 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.

P.S. dayOfWeek is .NET enum

Upvotes: 0

Views: 503

Answers (2)

S. John Fagone
S. John Fagone

Reputation: 184

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.

Upvotes: 1

Beingnin
Beingnin

Reputation: 2422

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

Upvotes: 0

Related Questions