LINQ GroupBy 除了空值
Posted
技术标签:
【中文标题】LINQ GroupBy 除了空值【英文标题】:LINQ GroupBy except null values 【发布时间】:2021-06-04 01:11:29 【问题描述】:我的目标是列出重复项,这就是我正在尝试的:
var duplicates = result
.GroupBy(x => x.col1)
.SelectMany(y => y.Count() > 1 ? y.Where(z => z.col2== decimal.Zero) : y)
.AsEnumerable()
.ToList();
但它已按col1
中的所有null
值分组。
示例输入
| col1 | col2 |
|--------|--------|
| 1/1/21 | 0.00 |
| 2/1/21 | 120.00 |
| 2/1/21 | 0.00 |
| 3/1/21 | 110.00 |
| null | 140.00 |
| null | 220.00 |
| 6/1/21 | 0.00 |
| 6/1/21 | 0.00 |
| 7/1/21 | 0.00 |
| null | 0.00 |
|--------|--------|
期望的输出
| col1 | col2 |
|--------|--------|
| 1/1/21 | 0.00 |
| 2/1/21 | 120.00 |
| 3/1/21 | 110.00 |
| null | 140.00 |
| null | 220.00 |
| 6/1/21 | 0.00 |
| 7/1/21 | 0.00 |
| null | 0.00 |
|--------|--------|
【问题讨论】:
可能是result.Where(x => x.col1 != null).GroupBy(x => x.col1)...
?
能否与我们分享您的数据模型?
请看编辑
@MK88 如果您有像2/1/21
或6/1/21
这样的副本,那么我们应该保留哪一个?
GroupBy(col1),但 col1 中的 null 值除外。
【参考方案1】:
对于选择重复项,此查询应该有效:
var duplicates = result
.GroupBy(x => x.col1)
.Where(y => y.Count() > 1)
.SelectMany()
.ToList();
【讨论】:
【参考方案2】:在您的GroupBy()
中,您需要处理col1
为空的情况并为组键分配唯一值。 Guid
可以很好地完成这项工作。试试这个:
var duplicates = result
.GroupBy(x => x.col1 == null ? Guid.NewGuid().ToString() : x.col1)
.Select(x => x.First())
.ToList();
【讨论】:
【参考方案3】:样本数据
假设您的域模型与此类似:
class DomainModel
public string Col1 get;
public double Col2 get;
public DomainModel(string col1, double col2)
Col1 = col1;
Col2 = col2;
出于测试目的,我将使用以下列表(填充您的示例输入):
var result = new List<DomainModel>
new DomainModel("1/1/21", 0.00),
new DomainModel("2/1/21", 120.00),
new DomainModel("2/1/21", 0.00),
new DomainModel("3/1/21", 110.00),
new DomainModel(null, 140.00),
new DomainModel(null, 220.00),
new DomainModel("6/1/21", 120.00),
new DomainModel("6/1/21", 0.00),
new DomainModel("7/1/21", 0.00),
new DomainModel(null, 0.00)
;
对相邻记录进行分组
如果我们可以依赖排序,那么我们可以将具有相同Col1
的相邻记录分组。为此,我们需要使用MoreLinq。
IEnumerable<IGrouping<string, DomainModel>> groupedResult = result.GroupAdjacent(c => c.Col1);
现在,如果我们使用以下命令打印出groupedResult
:
foreach (var group in groupedResult)
Console.WriteLine(group.Key ?? "null");
foreach (var model in group)
Console.WriteLine($"\tmodel.Col2");
然后我们会看到以下输出:
1/1/21
0
2/1/21
120
0
3/1/21
110
null
140
220
6/1/21
120
0
7/1/21
0
null
0
过滤掉不必要的项目
如果我正确理解您的要求,那么您希望:
显示那些组中键为null
的所有条目
显示具有单个条目的所有组
仅显示col2
不为0 且组中有更多条目的条目
这些可以翻译成以下查询:
var filteredResult = groupedResult.SelectMany(@group =>
@group.Key == null
? @group //If col1 is null then return as is
: @group.Count() == 1
? @group //If there is a single entry in a group then return as is
: @group.Where(c => Math.Abs(c.Col2) > 0.01)); //If there are multiple entries then return those where col2 is not 0
如果我们执行这个查询,输出将是预期的:
foreach (DomainModel model in filteredResult)
Console.WriteLine($"model.Col1 ?? "null" \t model.Col2");
1/1/21 0
2/1/21 120
3/1/21 110
null 140
null 220
6/1/21 120
7/1/21 0
null 0
【讨论】:
以上是关于LINQ GroupBy 除了空值的主要内容,如果未能解决你的问题,请参考以下文章