代码之家  ›  专栏  ›  技术社区  ›  Johnny Metz

如何使用linq删除项

  •  3
  • Johnny Metz  · 技术社区  · 6 年前

    string[] diseasesToRemove = new string[] { "D1", "D3", "D5" };
    

    我可以使用以下方法:

    for (int i = 0; i < healthGroup.DiseaseGroups.Length; i++)
    {
        var dgDiseases = new List<Disease>(healthGroup.DiseaseGroups[i].Diseases);
        for (int j = 0; j < dgDiseases.Count; j++)
        {
            if (diseasesToRemove.Contains(dgDiseases[j].Name))
            {                 
                dgDiseases.RemoveAt(j);
                j--;
            }
        }
        healthGroup.DiseaseGroups[i].Diseases = dgDiseases.ToArray();
    }
    

    不过,我相信有一个更好的方法使用Linq或其他东西。有?

    以下是课程:

    public class HealthGroup
    {
        public DiseaseGroup[] DiseaseGroups { get; set; }
    
        public HealthGroup(DiseaseGroup[] diseaseGroups)
        {
            DiseaseGroups = diseaseGroups;
        }
    }
    
    public class DiseaseGroup
    {
        public string Name { get; set; }
        public Disease[] Diseases;
    
        public DiseaseGroup(string name, Disease[] diseases)
        {
            Name = name;
            Diseases = diseases;
        }
    }
    
    public class Disease
    {
        public string Name { get; set; } = "My Disease";
        public int Risk { get; set; } = 7;
    
        public Disease(string name, int risk)
        {
            Name = name;
            Risk = risk;
        }
    
        public override string ToString()
        {
            return $"{Name} with risk {Risk}";
        }
    }
    

    Disease d1 = new Disease("D1", 1);
    Disease d2 = new Disease("D2", 2);
    Disease d3 = new Disease("D3", 3);
    Disease d4 = new Disease("D4", 4);
    Disease d5 = new Disease("D5", 5);
    Disease d6 = new Disease("D6", 6);
    Disease d7 = new Disease("D7", 7);
    
    DiseaseGroup dg1 = new DiseaseGroup("DG1", new Disease[] { d1, d2 });
    DiseaseGroup dg2 = new DiseaseGroup("DG2", new Disease[] { d3, d4, d5 });
    DiseaseGroup dg3 = new DiseaseGroup("DG3", new Disease[] { d6, d7 });
    
    HealthGroup healthGroup = new HealthGroup(new DiseaseGroup[] { dg1, dg2, dg3 });
    
    2 回复  |  直到 6 年前
        1
  •  6
  •   ProgrammingLlama Raveena Sarda    6 年前

    你可以用 Where 要将代码简化为:

    foreach (var diseaseGroup in healthGroup.DiseaseGroups)
    {
        diseaseGroup.Diseases 
            = diseaseGroup.Diseases.Where(g => !diseasesToRemove.Contains(g.Name)).ToArray();
    }
    

    Diseases List<Disease>

    public class DiseaseGroup
    {
        public string Name { get; set; }
        public List<Disease> Diseases;
    
        public DiseaseGroup(string name, Disease[] diseases)
        {
            Name = name;
            Diseases = new List<Disease>(diseases);
        }
    }
    

    然后您可以使用类似的代码,而无需生成新列表和新数组:

    for (int i = 0; i < healthGroup.DiseaseGroups.Length; i++)
    {
        for (int j = healthGroup.DiseaseGroups[i].Diseases.Count - 1; j >= 0; --j)
        {
            if (diseasesToRemove.Contains(healthGroup.DiseaseGroups[i].Diseases[j].Name))
            {                 
                healthGroup.DiseaseGroups[i].Diseases.RemoveAt(j);
            }
        }
    }
    

    我还修改了for循环以向后工作,以解决 --j 部分。

    而不是使用 string[] 对于 diseasesToRemove HashSet<string> 储存疾病。


    编辑以包含所需的一行:

    healthGroup.DiseaseGroups = healthGroup.DiseaseGroups.Select(g => { return g.Diseases = g.Diseases.Where(g => !diseasesToRemove.Contains(g.Name)).ToArray(); }).ToArray();
    

    这是滥用选择一点,但是:-)

        2
  •  2
  •   spender    6 年前

    .Contains

    不幸的是,linqto对象只执行开箱即用的内部连接,但是我保留的一个重用性很强的扩展方法简化了执行基于集合的左外部连接的工作。

    如果你在疾病和 diseasesToRemove healthGroup.DiseaseGroups[i].Diseases )与右侧收藏不符( 疾病商店搬家 ),则将删除任何匹配项。

    .LeftOuterJoin (如下所列),您可以按如下方式筛选数组:

    for (int i = 0; i < healthGroup.DiseaseGroups.Length; i++)
    {
        healthGroup.DiseaseGroups[i].Diseases =
            healthGroup.DiseaseGroups[i].Diseases
                .LeftOuterJoin(
                    diseasesToRemove,
                    d => d.Name,
                    dr => dr,
                    (d, dr) => ( d, dr ))
                .Where(x => x.dr == null)
                .Select(x => x.d)
                .ToArray();
    
    }
    

    public static class JoinExtensions
    {
        public static IEnumerable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(
            this IEnumerable<TLeft> leftSeq,
            IEnumerable<TRight> rightSeq,
            Func<TLeft, TKey> keySelectorLeft,
            Func<TRight, TKey> keySelectorRight,
            Func<TLeft, TRight, TResult> projectionSelector)
        {
            return leftSeq
                .GroupJoin(
                    rightSeq,
                    keySelectorLeft,
                    keySelectorRight,
                    (leftItem, rightItems) => new { leftItem, rightItems })
                .SelectMany(
                    x => x.rightItems.DefaultIfEmpty(),
                    (x, rightItem) => projectionSelector(x.leftItem, rightItem));
        }
    }