【问题标题】:Using linq to filter List of List使用 linq 过滤列表列表
【发布时间】:2016-10-13 19:55:22
【问题描述】:

我还没有很好地掌握 LINQ,感觉我的代码可以优化,所以寻求帮助。

我有一个 Patient 和 Med 类,每个类都有一个 public bool IsSelected。这些被包装到 PatientMeds 和 PatientMeds 类中;

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

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

我想过滤这些,所以如果 Patient.IsSelected == false 然后忽略它,并且只忽略 IsSelected == false 的 Meds;

现在,这段代码可以工作了:

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

但它看起来很“笨拙”。我怎样才能让它变得更好?

【问题讨论】:

  • LINQ 用于查询,而您当前的代码实际上正在修改现有 PatientMeds 对象的 Meds 列表。那么它应该是怎样的呢?
  • 您可以使用 LINQ 的 Any 方法,满足这两个要求

标签: c# linq


【解决方案1】:

我会使用ForEachRemoveAll方法

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

【讨论】:

  • 谢谢。我不知道 lambda 语法适用于 ForEach。
【解决方案2】:

您可以用新的PatientMeds 实例构建一个新列表,其中仅包含选定的患者和药物:

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

所以Where(p =&gt; p.IsSelected) 只选择选定的患者,Select(p =&gt; new PatientMeds { ... } 构造新的PatientMeds 实例。

最后p.Meds.Where(m =&gt; m.IsSelected).ToList() 构造了一个仅包含选定药物的新列表。

但尚不清楚构造新的PatientMedsList&lt;Med&gt; 实例是否可行。例如在new PatientMeds { ... },您需要映射PatientMeds 的所有属性。

【讨论】:

    【解决方案3】:

    尝试缩短以下 foreach 循环

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

    【讨论】:

      【解决方案4】:

      你可以试试RemoveAll

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

      作为引用类型,尽管您使用ToList() 方法创建了新列表,但它将指向相同的位置。所以,结果也会反映在patientsMeds变量上

      【讨论】:

      • 所有使用的方法都不是 LINQ :)
      • @IvanStoev,是的,它们是List calss 的 linqish 方法 :)
      • 他想跳过x.Patient.IsSelected == false的患者
      • @Valentin, IsSelectedMed 的属性,从以下代码行可以看出:...Meds.Where(m =&gt; m.IsSelected == false)。我的代码就是这样做的。
      • @fubo,感谢您的指点。我没注意。
      【解决方案5】:

      只需使用:

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

      【讨论】:

      • 如何过滤不需要的药物?
      • 糟糕,我错过了这个要求。这应该有效“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();"
      猜你喜欢
      • 2011-07-02
      • 2016-12-09
      • 1970-01-01
      • 2014-04-28
      • 1970-01-01
      • 2017-06-29
      相关资源
      最近更新 更多