分组与linq中的不同选择

Cor*_*ian 2 c# linq

我有以下用例:

Account Name  |  Ref 1 | Ref 2

Account1      |   Mike | John
Account1      |        |
Account1      |        |
Account2      |   Carl | Mike
Account2      |   Carl | Mike
Run Code Online (Sandbox Code Playgroud)

具有相同AccountName,Ref1,Ref2的行应该合并在一起,但是

如果包含空Ref1或Ref2不应合并.

结果应该是:

Account Name  |  Ref 1 | Ref 2

Account1      |   Mike | John
Account1      |        |
Account1      |        |
Account2      |   Carl | Mike
Run Code Online (Sandbox Code Playgroud)

AccountViewModel具有属性:AccountName,Ref1,Ref2

.

var result = new List<AccountViewModel >();

source.GroupBy(vm => new { vm.AccountName, vm.Ref1, vm.Ref2})
                  .Select(group =>
                  {
                      if (group.All(vm => string.IsNullOrWhiteSpace(vm.Ref1)) ||
                          group.All(vm => string.IsNullOrWhiteSpace(vm.Ref2)))
                      {
                          result.AddRange(group);
                      }
                      else
                      {
                          result.Add(new AccountViewModel
                          {                             
                              AccountName = group.Key.AccountName,                             
                              Ref1= group.First().Ref1,
                              Ref2= group.First().Ref2
                          });
                      }
                  });

 return result;
Run Code Online (Sandbox Code Playgroud)

我错过了GroupBy的功能吗?可以用另一种方式完成吗?

Raw*_*ing 5

三点建议.

首先,您可以使用SelectMany将每个组映射到一系列项目,并将序列合并为一起,而不是使用Select并将其添加到列表中作为副作用.

其次,您不必检查整个组的空/空白 - 您已经按这些值分组,因此它们对于组中的每个项应该是相同的.你可以检查一下钥匙.

第三,AccountViewModel如果您不想要,则无需创建新的代表组 - 您可以只使用组中的第一个项目.

return source
    .GroupBy(vm => new { vm.AccountName, vm.Ref1, vm.Ref2})
    .SelectMany(group =>
        {
            if (string.IsNullOrWhiteSpace(group.Key.Ref1) ||
                string.IsNullOrWhiteSpace(group.Key.Ref2))
            {
                // keep the group separate
                return (IEnumerable<AccountViewModel>)group;
            }
            else
            {
                // just use one item
                return new[] { group.First() };
            }
        });
Run Code Online (Sandbox Code Playgroud)