Эти виды работ по фильтрации можно выразить в виде объединений. Они решают проблему многократной итерации одной группы для проверки совпадений в другой группе (.Contains
здесь O (n) и часто вызывается ... этого не должно происходить).
К сожалению, linq-to-objects выполняет только внутренние соединения из коробки, но широко используемый метод расширения, который я использую, упрощает работу по выполнению лево-внешних объединений на основе множеств.
Если вы выполняете левостороннее объединение между заболеваниями и diseasesToRemove
, то вы выбираете элементы из левой коллекции объединения (healthGroup.DiseaseGroups[i].Diseases
), которые не соответствуют ничему в правой коллекции ( diseasesToRemove
), тогда вы удалите все, что соответствует.
Используя метод расширения .LeftOuterJoin
(указан ниже), вы можете фильтровать массивы следующим образом:
for (int i = 0; i < healthGroup.DiseaseGroups.Length; i++)
{
healthGroup.DiseaseGroups[i].Diseases =
healthGroup.DiseaseGroups[i].Diseases
.LeftOuterJoin(
diseasesToRemove,
d => d.Name,
dr => dr,
(d, dr) => ( d, dr ))
.Where(x => x.dr == null)
.Select(x => x.d)
.ToArray();
}
Метод расширения внешнего левого соединения:
public static class JoinExtensions
{
public static IEnumerable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(
this IEnumerable<TLeft> leftSeq,
IEnumerable<TRight> rightSeq,
Func<TLeft, TKey> keySelectorLeft,
Func<TRight, TKey> keySelectorRight,
Func<TLeft, TRight, TResult> projectionSelector)
{
return leftSeq
.GroupJoin(
rightSeq,
keySelectorLeft,
keySelectorRight,
(leftItem, rightItems) => new { leftItem, rightItems })
.SelectMany(
x => x.rightItems.DefaultIfEmpty(),
(x, rightItem) => projectionSelector(x.leftItem, rightItem));
}
}