Использование SelectMany () или сопоставление элементов двух последовательностей с LINQ (точечный синтаксис) - PullRequest
0 голосов
/ 23 февраля 2012

Мне нужно выбрать все элементы из набора, свойство Id которого содержится во втором наборе.Можно ли использовать «SelectMany ()» для этого?Какое наиболее эффективное / лучшее решение для этого типа проблемы сопоставления.

Пример : Выберите все DateRangeIds для данного ReportId посредством набора объединяющихся объектов.

Наборы :

  • Отчеты {ReportId, ReportName}
  • ReportDateRanges {DateRangeId, ReportId, ReportDateRangeId}
  • DateRanges {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, пожалуйста, не стесняйтесь критиковать этот код и предлагать любые предложения.Спасибо за помощь!

Ответы [ 4 ]

1 голос
/ 07 марта 2012

Вы можете присоединиться к коллекциям. Учитывая, что у вас есть 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);
1 голос
/ 24 февраля 2012

Ну, вы можете использовать метод Enumerable.Intersect (Of TSource) (IEnumerable (Of TSource), IEnumerable (Of TSource), 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 для своего пользовательского объекта, чтобы найти пересечение обоих перечислений.

Надеюсь, это поможет.

1 голос
/ 24 февраля 2012

Я думаю, ваш код прост и читабелен, но есть что-то нехорошее:

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, но вам это не нужно.

0 голосов
/ 24 февраля 2012

Вот один из способов сделать это:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...