Ответ 1
Теперь три варианта - первые два являются более общими, поскольку они не полагаются на MillionIntegerList
, который сортируется (который изначально не был указан). Третий предпочтительнее в случае, когда большой список уже отсортирован.
Вариант 1
Да, там определенно лучший способ сделать это, используя LINQ:
var common = MillionIntegerList.Intersect(TwoThousandIntegerList).ToList();
Это будет внутренне использовать HashSet<int>
, построенный с помощью TwoThousandIntegerList
, а затем просмотреть каждый элемент MillionIntegerList
внутри него - это будет намного более эффективно, чем каждый раз в течение TwoThousandIntegerList
.
Если вам нужны только не черные списки, вам нужно:
var valid = MillionIntegerList.Except(TwoThousandIntegerList).ToList();
Обратите внимание, что если вам нужно только один раз перебирать результаты, вы должны удалить вызов ToList
- я включил его для материализации результатов, чтобы их можно было исследовать несколько раз дешевле. Если вы просто повторяете, возвращаемое значение Intersect
или Except
будет просто передавать результаты, что делает его намного дешевле с точки зрения использования памяти.
Вариант 2
Если вы не хотите полагаться на детали реализации LINQ to Objects, но вы все же хотите использовать хэш-подход:
var hashSet = new HashSet<int>(TwoThousandIntegerList);
hashSet.IntersectWith(MillionIntegerList);
// Now use hashSet
Вариант 3
Подход к использованию того факта, что сортировка большого списка определенно будет полезной.
Предполагая, что вы не против сначала сортировать список с черным списком, вы можете написать реализацию потоковой (и общей цели), подобную этой (непроверенной):
// Note: to use this, you'd need to make sure that *both* sequences are sorted.
// You could either sort TwoThousandIntegerList in place, or use LINQ OrderBy
// method.
public IEnumerable<T> SortedIntersect<T>(this IEnumerable<T> first,
IEnumerable<T> second) where T : IComparable<T>
{
using (var firstIterator = first.GetEnumerator())
{
if (!firstIterator.MoveNext())
{
yield break;
}
using (var secondIterator = second.GetEnumerator())
{
if (!secondIterator.MoveNext())
{
yield break;
}
T firstValue = firstIterator.Current;
T secondValue = secondIterator.Current;
while (true)
{
int comparison = firstValue.CompareTo(secondValue);
if (comparison == 0) // firstValue == secondValue
{
yield return firstValue;
}
else if (comparison < 0) // firstValue < secondValue
{
if (!firstIterator.MoveNext())
{
yield break;
}
firstValue = firstIterator.Current;
}
else // firstValue > secondValue
{
if (!secondIterator.MoveNext())
{
yield break;
}
secondValue = secondIterator.Current;
}
}
}
}
}
(Вы можете взять IComparer<T>
, если хотите, вместо того, чтобы полагаться на сопоставимость T.)