Имена классов должны всегда быть описательными и очевидными. Если у Вас есть несколько доменов ответственности за Ваши классы тогда, они должны, вероятно, быть пересмотрены.
Аналогично для Вас пакеты. Они должны быть сгруппированы доменом ответственности. Каждый домен имеет свои собственные исключения.
Обычно не потеют он, пока Вы не добираетесь до точки, где это становится подавляющим и чрезмерно увеличенным в размерах. Тогда сядьте и не кодируйте, просто осуществляйте рефакторинг классы, компилируя регулярно, чтобы удостовериться, что все работает. Тогда продолжите, как Вы сделали прежде.
Как насчет:
var intersection = listOfLists
.Skip(1)
.Aggregate(
new HashSet<T>(listOfLists.First()),
(h, e) => { h.IntersectWith(e); return h; }
);
Таким образом, он оптимизируется за счет использования одного и того же HashSet повсюду и по-прежнему в одном операторе. Просто убедитесь, что listOfLists всегда содержит хотя бы один список.
Вы действительно можете использовать Пересечение
дважды. Однако я считаю, что это будет более эффективно:
HashSet<int> hashSet = new HashSet<int>(list1);
hashSet.IntersectWith(list2);
hashSet.IntersectWith(list3);
List<int> intersection = hashSet.ToList();
Конечно, это не проблема с маленькими наборами, но если у вас много больших наборов, это может быть значительным.
Обычно Enumerable.Intersect
требует для создания набора для каждого вызова - если вы знаете, что собираетесь выполнять больше операций с наборами, вы также можете оставить этот набор.
Как всегда, внимательно следите за производительностью и удобочитаемостью - цепочка методов вызов Intersect
дважды очень привлекателен.
РЕДАКТИРОВАТЬ: Для обновленного вопроса:
public List<T> IntersectAll<T>(IEnumerable<IEnumerable<T>> lists)
{
HashSet<T> hashSet = null;
foreach (var list in lists)
{
if (hashSet == null)
{
hashSet = new HashSet<T>(list);
}
else
{
hashSet.IntersectWith(list);
}
}
return hashSet == null ? new List<T>() : hashSet.ToList();
}
Или, если вы знаете, что он не будет пустым, и что Skip будет относительно дешевым:
public List<T> IntersectAll<T>(IEnumerable<IEnumerable<T>> lists)
{
HashSet<T> hashSet = new HashSet<T>(lists.First());
foreach (var list in lists.Skip(1))
{
hashSet.IntersectWith(list);
}
return hashSet.ToList();
}
Вы могли бы сделать следующее
var result = list1.Intersect(list2).Intersect(list3).ToList();
Попробуйте, это работает, но мне бы очень хотелось избавиться от .ToList () в совокупности.
var list1 = new List<int>() { 1, 2, 3 };
var list2 = new List<int>() { 2, 3, 4 };
var list3 = new List<int>() { 3, 4, 5 };
var listOfLists = new List<List<int>>() { list1, list2, list3 };
var intersection = listOfLists.Aggregate((previousList, nextList) => previousList.Intersect(nextList).ToList());
Обновление:
После комментария от @pomber, это можно избавиться от ToList ()
внутри вызова Aggregate
и переместить его за пределы, чтобы выполнить его только один раз. Я не тестировал на производительность, будет ли предыдущий код быстрее нового. Необходимо указать параметр универсального типа метода Aggregate
в последней строке, как показано ниже:
var intersection = listOfLists.Aggregate<IEnumerable<int>>(
(previousList, nextList) => previousList.Intersect(nextList)
).ToList();