Я хочу преобразовать список A
A = {1, 12, 3, 3, 3, 8, 5, 5 }
в список B
B = {1, 12, 3, 8, 5 }
Как видите, пункты 3 и 5 повторяются в A
, и эти повторы исключаются в B
.
Код, который я создал для этого, следующий:
public IEnumerable<int> FilterRepeatingElements(IEnumerable<int> source)
{
return source
.Select(x => (IEnumerable<int>)new[] { x })
.Aggregate((a, b) => a.Last() != b.First() ? a.Concat(b) : a);
}
Это работает, но мне интересно, есть ли более выразительный способ сделать это с помощью «LINQ», с помощью классических методов .NET или методов из библиотеки, например Morelinq.
Спасибо!
РЕДАКТИРОВАТЬ
Я обнаружил, что у моего решения проблемы с таким вариантом использования:
FilterRepeatingElements(MoreEnumerable.Random()).Take(10)
MoreEnumerable.Random()
генерирует бесконечную последовательность. Выполнение такого кода приводит к зависанию выполнения.
1 ответ
Хотя ответ aepot является хорошим ответом и получил мое одобрение, он работает только для типа int. Я знаю, что вопрос для примера использует int в своем коде, но если вы хотите, чтобы он работал для всех типов данных, необходимо немного изменить код.
public static class EnumerableExtensions
{
public static IEnumerable<TSource> FilterRepeatingElements<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
using (var enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
var item = enumerator.Current;
yield return item;
while (enumerator.MoveNext())
{
if (!comparer.Equals(item, enumerator.Current))
{
item = enumerator.Current;
yield return item;
}
}
}
}
}
public static IEnumerable<TSource> FilterRepeatingElements<TSource>(this IEnumerable<TSource> source)
{
return FilterRepeatingElements(source, EqualityComparer<TSource>.Default);
}
}
Это будет работать для любого типа и принимает те же параметры, что и linq Distinct, поскольку мы делаем «своего рода» отличное.
var data = new int[] { 1, 12, 3, 3, 3, 8, 5, 5 };
var postData = data.FilterRepeatingElements().ToArray();
var items = new string[] { "A", "A", "B", "C", "C", "D", "D" };
var postItems = items.FilterRepeatingElements().ToArray();