#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. Итак, когда это «не приведет к дублированию», это приведет только к различным значениям? Это не то, что мне нужно. Это значение не уникально, но это не означает, что две записи с одинаковым значением представляют одну и ту же сущность.