多个Group by LINQ扩展方法

时间:2018-07-18 12:31:59

标签: c# asp.net entity-framework linq

我有一个C#.NET应用程序,想在多种情况下进行分组依据。 我有一个这样的列表:

var testq = new List<TestQuestion>()
            {
                new TestQuestion
                {
                    Id = 1,
                    QuestionId = 1,
                    SelectedAnswerId = null
                },
                new TestQuestion
                {
                    Id = 2,
                    QuestionId = 2,
                    SelectedAnswerId = 1
                },
                new TestQuestion
                {
                    Id =3,
                    QuestionId = 1,
                    SelectedAnswerId = 1
                },
                new TestQuestion
                {
                    Id = 4,
                    QuestionId = 3,
                    SelectedAnswerId = 5
                },
                new TestQuestion
                {
                    Id = 5,
                    QuestionId = 1,
                    SelectedAnswerId = 2
                },
                new TestQuestion
                {
                    Id = 6,
                    QuestionId = 3,
                    SelectedAnswerId = 3
                },
                new TestQuestion
                {
                    Id =7,
                    QuestionId = 4,
                    SelectedAnswerId = null
                },
                new TestQuestion
                {
                    Id =8,
                    QuestionId = 5,
                    SelectedAnswerId = null
                },
            };

我的代码是:

  var result = testq
                .Where(p => p.SelectedAnswerId.HasValue)
                .GroupBy(p => p.QuestionId)
                .Select(p => p.FirstOrDefault())
                .ToList();

现在,结果ID为(2,3,4) 但是结果不正确...

结果应该是这样的: ID->(2,3,4,7,8)

我要根据QuestionID字段对结果进行分组,并且第一个没有(SelectedAnswerId)字段值的记录为空,

此外,无论输出中字段的值(SelectedAnswerId)如何,都记录其中问题ID仅存在一次的记录。就是说,列表中的最后两项

请引导我...

3 个答案:

答案 0 :(得分:2)

尝试一下:

var result = testq
            .Where(p => p.SelectedAnswerId.HasValue || testq.Count(x => x.QuestionId == p.QuestionId) == 1)
            .GroupBy(p => p.QuestionId)
            .Select(p => p.FirstOrDefault())
            .Distinct()
            .ToList();

C# Fiddle

答案 1 :(得分:0)

您必须在SelectedAnswerId而不是Select子句中过滤Where。请尝试以下

 var result = testq
             .GroupBy(p => p.QuestionId)
             .Select(p => 
              {
                 var grouped = p.ToList(); //Get the groupBy list
                 TestQuestion testQuestion = grouped.FirstOrDefault(x => x.SelectedAnswerId.HasValue); //Get anything with AnswerId
                 return testQuestion ?? grouped.FirstOrDefault(); //If not not available with Answer then get the First or Default value
              })
              .ToList();

C# Fiddle和测试数据。

答案 2 :(得分:0)

尽管在GroupBy之后,每个组中元素的顺序都得到了明确定义(请参见Enumerable.GroupBy,但似乎您想要的元素不是每个组中的第一个元素。

您希望每个组的First元素具有一个不为空的SelectedAnswerId,或者如果没有这样的元素,则希望每个组的First元素具有一个不为空的SelectedAnswerId。

如何?

var result = testQ.GroupBy(question => question.QuestionId);
    // every group contains a sequence of questions with same questionId
    // select the ones with a null SelectedAnswerId and the ones with a non-null value
    .Select(group => new
    {
        NullSelectedAnswer = group
            .Where(group.SelectedAnswerId == null)
            .FirstOrDefault(),
        NonNullselectedAnswer = group
            .Where(group.SelectedAnswerId != null)
            .FirstOrDefault(),
    })
    // if there is any NonNullSelectedAnswer, take that one, otherwise take the null one:
    .Select(selectionResult => selectionResult.NonNullSelectedAnswer ??
                               selectionResult.NullSelectedAnswer);