使用SelectMany()或使用LINQ(点语法)匹配两个序列的元素

本文关键字:两个 元素 语法 SelectMany LINQ 使用 | 更新日期: 2023-09-27 18:25:32

我需要从一个集合中选择所有元素,该集合的Id属性包含在第二个集合中。可以使用"SelectMany()"来实现这一点吗?对于这类匹配问题,什么是最有效/最好的解决方案。

示例:通过联接实体集的方式为给定ReportId选择所有DateRangeId。

集合

  • 报告{ReportId,ReportName}
  • ReportDateRanges{DateRangeId,ReportId,ReportDateRangeId}
  • 日期范围{DateRangeId,DateRangeName}

这是我的解决方案代码。我不确定这是否是正确的方法,但这确实解决了我所描述的问题:

    var report = Reports.Take(1).FirstOrDefault();
    int reportId = Convert.ToInt32(report.Id);
    var dateRangeIds = ReportDateRanges.Where(rdr => rdr.ReportId == reportId).OrderBy(it => it.DateRangeId).Select(it => it.DateRangeId);
    var dateRanges = DateRanges.Where(dateRange => dateRangeIds.Contains(dateRange.Id));

LINQ专家,请随时评论此代码并提供任何建议。谢谢你的帮助!

使用SelectMany()或使用LINQ(点语法)匹配两个序列的元素

好吧,你可以使用Enumerable.Intersect(Of-TSource)方法(IEnumerable(Of-TSource),IEnumeraable(Of-TSources),IEqualityComparer(Of TSource))

例如:

var list1 = new List<int> {1,2,3,4,5,6,7,8};
var list2 = new List<int> {9,10,11,12,13,4,5};
list1.Intersect(list2);

结果

4,5

使用链接中指定的重载,您可以为自定义对象指定EqualityComparer,以便找到两个枚举的交集。

希望这能有所帮助。

我认为您的代码简单可读,但也有一些不好的地方:

var report = Reports.Take(1).FirstOrDefault();

你可以写:

var report = Reports.FirstOrDefault();

在这一行:

var dateRangeIds = ReportDateRanges.Where(rdr => rdr.ReportId == reportId)
                                   .OrderBy(it => it.DateRangeId)
                                   .Select(it => it.DateRangeId);

你使用了orderby,但你不需要这个。

您可以加入集合。假设您有reportId,则可以发出此查询。

Reports
    .Where(report => report.ReportId == reportId)
    .Join(ReportDateRanges, 
              report => report.ReportId, 
              rdr => rdr.ReportId,
              (report, reportDateRange) => reportDateRange)
    .Join(DateRanges,
              rdr => rdr.DateRangeId,
              dateRange => dateRange.DateRangeId,
              (reportDateRange, dateRange) => dateRange);

这里有一种方法:

IEnumerable<SomeTypeWithAnIDProperty> sourceSequence = //whatever
IEnumerable<TypeOfTheIDProperty> ids = //whatever
var selectedItems = 
    from sourceObject in sourceSequence
    join id in ids
        on sourceObject.ID equals id
    select sourceObject;

或者,使用您的示例

var dateRangeIds = ReportDateRanges
    .Where(rdr => rdr.ReportId == reportId)
    .OrderBy(it => it.DateRangeId)
    .Select(it => it.DateRangeId);
var dateRanges = DateRanges.Join(dateRangeIds, dateRange => dateRange.Id, id => id, (dateRange, id) => dateRange);