如何在LINQ中使用GroupBy查找缺少的项目?

时间:2018-03-23 14:25:22

标签: c# linq

我有一个这样的场景,我有这些项目的集合

public class Submission {
    public DateTime ProcessedDate { get; set; }
    public string UserName { get; set; }
}

我需要检查一组用户名,例如:

string[] names = new string{"Paul", "John", "George", "Ringo"};

我想找出哪些日期缺少提交(日期并非所有这些用户名都有条目)。想象一下测试数据如:

var submissions = new List<Submission>();
submissions.Add(new Submission() { ProcessedDate = new DateTime(2018, 1, 1), UserName = "Paul" });
submissions.Add(new Submission() { ProcessedDate = new DateTime(2018, 1, 1), UserName = "John" });
submissions.Add(new Submission() { ProcessedDate = new DateTime(2018, 1, 1), UserName = "George" });
submissions.Add(new Submission() { ProcessedDate = new DateTime(2018, 1, 1), UserName = "Ringo" });
submissions.Add(new Submission() { ProcessedDate = new DateTime(2018, 1, 2), UserName = "Paul" });
submissions.Add(new Submission() { ProcessedDate = new DateTime(2018, 1, 2), UserName = "John" });
submissions.Add(new Submission() { ProcessedDate = new DateTime(2018, 1, 3), UserName = "George" });
submissions.Add(new Submission() { ProcessedDate = new DateTime(2018, 1, 3), UserName = "Ringo" });

1/1有所有用户名的提交,但是1/2和1/3都缺少条目,我如何返回缺失的一组(缺少日期和该日期失踪的用户)?< / p>

2018-01-02 - George,Ringo

2018-01-03 - 保罗,约翰

3 个答案:

答案 0 :(得分:3)

如果您只需要日期,请使用此查询:

var result = submissions.GroupBy(o => o.ProcessedDate)
    .Where(o => names.Any(x => !o.Any(s => s.UserName == x)))
    .Select(o => o.Key)
    .ToList();

如果您需要Submission个对象列表,请使用以下对象:

var resultWithSubmissions = submissions.GroupBy(o => o.ProcessedDate)
    .Where(o => names.Any(x => !o.Any(s => s.UserName == x)))
    .SelectMany(o => o)
    .ToList();

如果您需要每个日期缺少用户名列表,请使用以下查询:

var resultWithMissingNames = submissions.GroupBy(o => o.ProcessedDate)
    .Where(o => names.Any(x => !o.Any(s => s.UserName == x)))
    .Select(o => new { ProcessedDate = o.Key, MissingNames = string.Join(",", names.Except(o.Select(x => x.UserName)))})
    .ToList();

答案 1 :(得分:2)

我认为您正在寻找的是:

var result = submissions
                 .GroupBy(s => s.ProcessedDate)
                 .Select(g => new { Date = g.Key, Names = names.Except(g.Select(s => s.UserName)) })
                 .Where(g => g.Names.Any());

答案 2 :(得分:0)

var names = new[] { "Paul", "John", "George", "Ringo" };
var dates = new[] { new DateTime(2018, 1, 1), new DateTime(2018, 1, 2),
    new DateTime(2018, 1, 3) };

var missingUsersByDate = submissions
    .GroupBy(s => s.ProcessedDate)
    .Select(g => new { ProcessDate = g.Key,
        MissingUsers = names.Except(g.Select(s => s.UserName)) })
    .Where(g => g.MissingUsers.Any())
    .ToDictionary(k => k.ProcessDate, v => v.MissingUsers);

// Paul, John
var missingUsers = missingUsersByDate[new DateTime(2018, 1, 3)];

// 2018.1.2 -> George, Ringo
// 2018.1.3 -> Paul, John
foreach(var usersDatePair in missingUsersByDate)
{
    DateTime date = usersDatePair.Key;
    string[] users = usersDatePair.Value.ToArray();
}

此方法按日期对提交进行分组,并使用匿名类型存储有关日期和缺少用户的信息。 然后过滤此结果以删除没有丢失学生的日期,然后作为字典返回。