c# - 使用 LINQ 删除多个 List<> 对象中的重复对象

标签 c# linq

我有几个看起来像这样的类(针对 SO 进行了简化):

public class Result
{
    pubic List<Review> Reviews { get; set; }
}

public class Review
{
    public string Name { get; set; }
    public int Amount { get; set; }
}

我开始的是 List<Result>目的。列表中的每个“Result”对象显然都包含另一个 List 属性。在每个“结果”对象中,其评论列表永远不会有重复的“名称”属性。但是,在预期的情况下,列表中的所有结果对象都会有重复的“名称”属性。

例如:

var results = new List<Result>();

var result1 = new Result();
result1.Reviews = new List<Review>();
result1.Reviews.Add(new Review { Name = "ABC", Amount = 5 });
result1.Reviews.Add(new Review { Name = "DEF", Amount = 4 });
results.Add(result1);

var result2 = new Result();
result2.Reviews = new List<Review>();
result2.Reviews.Add(new Review { Name = "ABC", Amount = 1 });
result2.Reviews.Add(new Review { Name = "WRA", Amount = 4 });
results.Add(result2);

var result3 = new Result();
result3.Reviews = new List<Review>();
result3.Reviews.Add(new Review { Name = "ABC", Amount = 2 });
result3.Reviews.Add(new Review { Name = "ARA", Amount = 4 });
results.Add(result3);

因此,您可以看到在结果列表中,名称“ABC”在评论列表中重复。我需要做的是编写一个 LINQ 查询,对 results 进行操作对象将从子列表中删除所有重复的 Review 对象,最高的除外。因此,在这种情况下,result2 和 result3 的“ABC”评论都将从列表中完全删除。

关于如何使用 LINQ 执行此操作的任何建议?我也在寻找自己的解决方案,只是想我会在这里发帖看看它是否比我自己弄清楚更快。 :)

最佳答案

不要为 Reviews 使用公共(public)属性,而要使用私有(private)属性。然后提供您自己的 add() 方法并插入或替换元素。

修改 Result 的 Equals 方法,因此当名称匹配时,Results 被线程化为“相等”。 (这是不正确的,但是使得 contains()indexOf() 在检查项目是否存在时以我们希望的方式工作):

public class Review
    {
        public string Name { get; set; }
        public int Amount { get; set; }

        public override bool Equals(System.Object obj)
        {
            // If parameter is null return false.
            if (obj == null)
            {
                return false;
            }


            Review r = obj as Review;
            if ((System.Object)r == null)
            {
                return false;
            }

            //only compare on the name.
            return Name.Equals(r.Name);
        }
    }

现在,结果和添加方法:

class Result
    {
        private List<Review> _Reviews = new List<Review>();
        public List<Review> Reviews { get { return _Reviews; } }

        public void Add(Review r)
        {
            if (_Reviews.Contains(r))
            {
                //check if difference on Amount
                int index = _Reviews.IndexOf(r);
                Review currentReview = _Reviews[index];

                if (currentReview.Amount < r.Amount)
                {
                    //replace
                    _Reviews.RemoveAt(index);
                    _Reviews.Add(r);
                }
                //else keep existing
            }
            else
            {
                //Add
                _Reviews.Add(r);
            }
        }
    }

最后,您可以将每条评论添加到相同结果,而无需处理任何事情:

var result = new Result();

            result.Add(new Review { Name = "ABC", Amount = 5 });
            result.Add(new Review { Name = "DEF", Amount = 4 });
            result.Add(new Review { Name = "ABC", Amount = 1 });
            result.Add(new Review { Name = "WRA", Amount = 4 });
            result.Add(new Review { Name = "ABC", Amount = 2 });
            result.Add(new Review { Name = "ARA", Amount = 4 });

            foreach (Review r in result.Reviews)
            {
                MessageBox.Show(r.Name + ": " + r.Amount);
            }

无论您以何种顺序提供添加调用,所包含的元素都是:

ABC:5 
DEF:4
WRA:4
ARA:4

(如果需要,按名称排序)

关于c# - 使用 LINQ 删除多个 List<> 对象中的重复对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25430234/

相关文章:

c# - 大数字的 IsNumeric Helper 方法

.net - 没有 key 的 Entity Framework 删除

c# - 将两个 LINQ 表达式合并为一个

c# - 导航 UWP-navigateuri : msnweather

c# - 我应该在 SqlClr 中运行 F# 吗?

c# - 在 C# 中获取属性值(反射)的最快方法

c# - 过滤 IEnumerable<string> 不需要的字符串

c# - 我无法理解 GroupJoin 在数据库关系中需要它的地方

c# - 从 WiX 安装程序传递标志以合并模块?

C#:达到最大池大小的根本原因