【问题标题】:Get a list of duplicate entries in List based on 2 fields using Linq使用 Linq 根据 2 个字段获取 List 中重复条目的列表
【发布时间】:2014-09-03 03:39:20
【问题描述】:

我正在使用以下 Linq 来确定在某些自定义验证期间我的列表中是否有任何无效条目 - 我想知道是否有人根据他们工作的公司分配了相同的编号:

var duplicates = Persons.GroupBy(x => 
                new { x.Number, x.CompanyId}, (key) => new { key.Number, key.CompanyId })
                .Where(y => y.Count() > 1);

对于一个简单的 Person 类:

class Person
{
    public string Name { get; set; }
    public int Number { get; set; }
    public int CompanyId { get; set; }
}

所以构建一些测试数据:

List<Person> Persons = new List<Person>();
// add people (users would do this!)
Persons.Add(new Person() { Name = "Person 1", Number = 1, CompanyId = 1 }); // invalid
Persons.Add(new Person() { Name = "Person 2", Number = 2, CompanyId = 1 });
Persons.Add(new Person() { Name = "Person 3", Number = 3, CompanyId = 1 });
Persons.Add(new Person() { Name = "Person 4", Number = 1, CompanyId = 1 }); // invalid
Persons.Add(new Person() { Name = "Person 5", Number = 2, CompanyId = 2 }); // invalid
Persons.Add(new Person() { Name = "Person 6", Number = 2, CompanyId = 2 }); // invalid

检查是否有重复并处理:

var duplicates = Persons.GroupBy(x => 
                new { x.Number, x.CompanyId}, (key) => new { key.Number, key.CompanyId })
                .Where(y => y.Count() > 1);

if (duplicates.Any())
{
    // build a string
}

我想要做的是获取无效条目的列表并通知用户。所以在上述情况下,我想输出以下文本:

  • 已为公司 #1 分配了相同的编号 #1,人员 1 和人员 4。
  • 已为公司 #2 分配了相同的编号 #2,第 5 人和第 6 人。

【问题讨论】:

  • 你有没有想过... Persons.Where(p => (p.Number == p.CompanyId)) 然后对结果进行相应的分组
  • 编号 == 公司?这不起作用,因为 Number 与 Company 无关。每个公司都有自己的编号系统。 Number 和 Company 必须为 GroupBy 中的键。
  • 你应该澄清为什么Person Number或CompanyId无效,是因为重复的号码还是什么!

标签: c# linq group-by


【解决方案1】:

更改您的分组方式以将名称作为选择项和分组方式返回。 String.Join 然后将合并列表

var duplicates = Persons
    .GroupBy(key => new { key.Number, key.CompanyId }, a=>a.Name)
    .Where(y => y.Count() > 1);

var sb = new StringBuilder();
foreach (var duplicate in duplicates)
{
    sb.AppendLine(String.Format("{0} have been assigned the same Number {1} for Company #{2}",
                                String.Join(" and ", duplicate), duplicate.Key.Number,
                                duplicate.Key.CompanyId));
}
var message = sb.ToString();

现在检查消息是否为空,以了解您是否有重复项,而不是 Any() 语句。

【讨论】:

  • 谢谢查尔斯。效果很好。还在消化。
【解决方案2】:

我发现使用查询语法而不是流畅的语法更容易正确地编写分组 LINQ 查询。这是一个可以为您提供所需字符串的查询:

from p in Persons   
group p by new { p.Number, p.CompanyId } into g
where g.Count () > 1
select string.Format(
    "{0} have been assigned the same number #{1} for company {2}",
    string.Join(" and ", g.Select (x => x.Name)),
    g.Key.Number,
    g.Key.CompanyId);

请注意,该查询不能用作 LINQ-to-SQL/实体查询,它只能针对内存中的数据。

【讨论】:

  • 感谢史蒂夫的信息。幸运的是,我正在使用内存检查,因为数据已加载到我的 EF ObjectStateManager 中,我实际上是在其中执行此操作。仍然需要我一些时间来适应
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
  • 2010-10-13
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多