Извлекать элементы IEnumerable, ключевое значение которых равно одному из ключевых значений в IEnumerable

#c# #.net #linq #collections #ienumerable

#c# #.net #linq #Коллекции #ienumerable

Вопрос:

Я хочу извлечь все элементы из последовательности IEnumerable, ключевое значение которых равно одному из ключевых значений в другой последовательности IEnumerable. Пожалуйста, учтите, что первая последовательность имеет тип ‘T’, где T -:

 class T
{
    int SpecificValue;
    // other payload
}
  

а вторая последовательность имеет тип ‘U’, где U -:

 class U
{
    int SpecificValueOfSameType;
    // other payload (different from class T)
}
  

Возможно ли это?

В качестве побочного узла: я использовал термин «Ключевое» значение, но нет гарантии, что это значение уникально в любой из обеих последовательностей. Это должно просто помочь объяснить мои требования немного более подробно. В реальном коде, я могу представить, есть какой-то параметр Compare-Func).

Ответ №1:

Звучит так, как будто вы ищете Join .

 ts.Join(us, t => t.SpecificValue, u => u.SpecificValueOfSameType, (t, u) => new Something)
  

Комментарии:

1. Нет, я не хочу объединять / архивировать эти обе коллекции. Я просто хочу извлекать значения из одной коллекции в зависимости от условий, связанных с другой.

2. Не приведет ли такое объединение к дублированию? {1, 1, 2, 2}, сопоставленных с {1, 1, 2, 2, 2, 2} = 12 результаты. Должно быть 4 результата.

Ответ №2:

попробуй это:

 Ts.Where(t => Us.Select(u => u.SpecificValueOfSameType).Contains(t.SpecificValue))
  

Комментарии:

1. Это то, что у меня уже есть. Думал, что есть что-то более простое. (Кстати. Я думаю, вы хотели написать «.Содержит(т.SpecificValue)». Итак, «t» вместо «y»).

2. другой способ — использовать join, но я стараюсь избегать объединений, если мне нужно выбирать элементы только из одной коллекции; исправлено значение «t» thx

Ответ №3:

Как показал К. Иванов, вы можете использовать Contains — но если ваша коллекция довольно большая, вам лучше сначала поместить их в HashSet:

 var keys = new HashSet<T>(us.Select(u => u.SpecificValueOfSameType));
var query = ts.Where(t => keys.Contains(t.SpecificValue));
  

РЕДАКТИРОВАТЬ: я пропустил тот факт, что в любой коллекции могут быть дубликаты ключей. Это нормально для приведенного выше кода, но не будет хорошо работать с join (по крайней мере, не без Distinct вызова тоже).

Не совсем понятно, что вы подразумеваете под параметром «Compare-Func». Если это просто способ извлечения ключа из последовательности, это нормально. Если это функция для сравнения равенства двух ключей, это другое дело. Это означало бы, что вы не могли иметь в виду хэширование.

Ответ №4:

нет гарантии, что это значение уникально в любой из обеих последовательностей.

Что ж, это дает понять, что вы хотите держаться подальше от большинства объединений.

Как насчет группового объединения? Этот тип соединения не приведет к дублированию при наличии нескольких совпадений.

 from t in tSource
join u in uSource
  on t.SpecificValue
  equals u.SpecificValueOfSameType
  into g
where g.Any()
select t;
  

также записывается как:

 tSource.GroupJoin(uSource,
  t => t.SpecificValue,
  u => u.SpecificValueOfSameType,
  (t, g) => new {t, g})
.Where(x => x.g.Any())
.Select(x => x.t)
  

Комментарии:

1. Итак, когда это «не приведет к дублированию», это приведет только к различным значениям? Это не то, что мне нужно. Это значение не уникально, но это не означает, что две записи с одинаковым значением представляют одну и ту же сущность.