c# - 使用 groubBy 的 LINQ 过滤器查询
问题描述
我目前正在开发一个 .NET Core 应用程序。
我需要按以下要求过滤 LINQ 查询:
- Id:如果没有ContactId,只选择一次Id(1)
- Id 和 ContactId:如果存在过滤 Id (1) 并添加 Id 和 Contact Id 对 (1, 1)
- Id 和 ContactId 对必须是唯一的,但可以变化如下:(1, 1), (1, 5)
- 必须删除空对象
public class SearchResult
{
public int? Id {get; set;}
public int? ContactId {get; set;}
}
public class Program
{
public static void Main()
{
var searchResults = new List<SearchResult>
{
new SearchResult { Id = 1 },
new SearchResult { },
new SearchResult { Id = 2 }, // yes
new SearchResult { Id = 3 }, // yes
new SearchResult { Id = 4 }, // yes
new SearchResult { Id = 5 },
new SearchResult { Id = 5, ContactId = 3 }, // yes
new SearchResult { Id = 1, ContactId = 1 }, // yes
new SearchResult { Id = 1, ContactId = 5 }, // yes
new SearchResult { Id = 8, ContactId = 4 }, // yes
new SearchResult { Id = 1 },
new SearchResult { Id = 2 },
new SearchResult { Id = 10 }, // yes
new SearchResult { Id = 11 }, // yes
new SearchResult { Id = 12 }, // yes
};
// unfortunately this LINQ query does not work correctly:
var result = searchResults
.OrderBy(x => x.Id)
.ThenBy(x => x.ContactId)
.GroupBy(p => new { p.Id, p.ContactId })
.Select(x => x.First());
foreach(var sr in result){
Console.WriteLine(sr.Id + " " + sr.ContactId);
}
}
预期的结果应该是:
1 1
1 5
2
3
4
5 3
8 4
10
11
12
不幸的是,我的 LINQ 查询无法正常工作。
你知道如何解决这个问题并根据规则过滤 LINQ 查询吗?
解决方案
我建议这样的事情。下面我们GroupBy
再分析一下各个组。最后,我们将 s变平 group
为IEnumerable<SearchResult>
(please, fiddle )
为了删除重复项,我们应该知道如何比较项目是否相等,然后调用Distinct
. 我们可以为此实现 IEqualityComparer:
private class MyEqualityComparer : IEqualityComparer<SearchResult> {
public bool Equals(SearchResult x, SearchResult y) {
if (ReferenceEquals(x, y))
return true;
else if (null == x || null == y)
return false;
return x.Id == y.Id && x.ContactId == y.ContactId;
}
public int GetHashCode(SearchResult obj) => (obj != null && obj.Id.HasValue)
? obj.Id.Value
: 0;
}
最终代码:
var result = searchResults
.Where(item => item.ContactId.HasValue || item.Id.HasValue)
.Distinct(new MyEqualityComparer()) // remove duplicates
.GroupBy(item => item.Id)
.Select(group => group.Any(item => item.ContactId.HasValue)
? group.Where(item => item.ContactId.HasValue)
: group.Take(1))
.SelectMany(group => group);
我们来看一下:
Console.WriteLine(string.Join(Environment.NewLine, result
.Select(item => $"{item.Id} {item.ContactId}")));
结果:
1 1
1 5
2
3
4
5 3
8 4
10
11
12
推荐阅读
- swift - 如何使用打字稿将快照值转换为字典值?
- javascript - 如何使用 Javascript 中的单击按钮来更改笔划的颜色?
- python-3.x - DLL 加载失败:找不到指定的模块。在 matplotlib 程序中
- flutter - 在某些情况下我可以跳过 BlocBuilder 渲染吗?
- java - 如何通过在android中使用位置来获取模态类数据
- javascript - 在使用 multer-s3-transform 上传到 s3 之前使用 imagemin 转换照片
- javascript - 尝试在 React 中使用状态存储数据以便以后可以访问时遇到问题
- json - 确定 API 是 RPC 还是 REST
- python - TypeError: 'numpy.int32' object is not iterable - 使用 sklearn_crfsuite 时出错
- c++ - 有没有一种方法可以将本地 Windows 调试器的输出集成到 Visual Studio 的界面中?