pgee70
pgee70

Reputation: 3974

Using linq to filter List of List

I still don't have a good grasp on LINQ yet, and felt like my code could be optimised so looking for help.

I have a Patient and Med Class, each have a public bool IsSelected. These are wrapped into the PatientMeds and PatientsMeds Classes;

public class PatientMeds
{
    public Patient Patient;
    public List<Med> Meds;
}

public class PatientsMeds
{
    public List<PatientMeds> PatientMedsList;
}

I want to filter these, so if the Patient.IsSelected == false then ignore it, and ignore only the Meds where IsSelected == false;

Now, this code works:

List<PatientMeds> patientMedsList = PatientsMeds.PatientMedsList
    .Where(x => x.Patient.IsSelected)
    .ToList();
foreach (PatientMeds patientMeds in patientMedsList)
{
    var medsToRemove = patientMeds.Meds.Where(m => m.IsSelected == false).ToList();
    foreach (Med med in medsToRemove)
    {
        patientMeds.Meds.Remove(med);
    }
}

But it just seems 'clunky'. How can i make it better?

Upvotes: 0

Views: 135

Answers (5)

kashi_rock
kashi_rock

Reputation: 557

just use:

var bb = patientMedsList.Where(p => p.Patient.IsSelected).ToList().Select(p => new PatientMeds { Patient = p.Patient, Meds = p.Meds.Where(m => m.IsSelected).ToList() }).ToList();

Upvotes: 0

Adil Mammadov
Adil Mammadov

Reputation: 8676

You can try RemoveAll

patientsMeds
    .PatientMedsList
    .Where(m => m.Patient.IsSelected)
    .ToList()
    .ForEach(m => m.Meds.RemoveAll(med => !med.IsSelected));

As being reference type, despite you create new list using ToList() method, it will point to same location. So, the result also will be reflected at patientsMeds variable

Upvotes: 1

CodeCaster
CodeCaster

Reputation: 151588

You could construct a new list with new PatientMeds instances containing only selected patients and meds:

var selectedPatientsWithSelectedMeds = patientMedsList.Where(p => p.IsSelected)
                                      .Select(p => new PatientMeds
                                      {
                                        Patient = p.Patient,
                                        Meds = p.Meds.Where(m => m.IsSelected).ToList()
                                      })
                                      .ToList();

So the Where(p => p.IsSelected) only selects selected patients, and the Select(p => new PatientMeds { ... } constructs new PatientMeds instances.

Finally p.Meds.Where(m => m.IsSelected).ToList() constructs a new list with only selected meds.

But it's not clear whether constructing new PatientMeds and List<Med> instances is viable. For example at new PatientMeds { ... } you will need to map all properties of PatientMeds.

Upvotes: 2

Ritwik Sen
Ritwik Sen

Reputation: 296

Try shortening the following foreach loop

foreach (PatientMeds patientMeds in patientMedsList)
{
    patientMeds.Meds.RemoveAll(m => m.IsSelected == false);   
}

Upvotes: 1

Valentin
Valentin

Reputation: 5488

I would use ForEach RemoveAll method

List<PatientMeds> patientMedsList = PatientsMeds.PatientMedsList
    .Where(x => x.Patient.IsSelected)
    .ToList();
patientMedsList.ForEach(p=> p.Meds.RemoveAll(m=>!m.IsSelected));

Upvotes: 3

Related Questions