Is there a function to remove consequent values (i.e. 14, 14 -> 14
, 12, 12 -> 12
)?
The following list ([12, 14, 14, 12, 12, 14]
):
List<string> foo = new List<string> { 12, 14, 14, 12, 12, 14 };
to the list [12, 14, 12, 14]
?
Is there a function to remove consequent values (i.e. 14, 14 -> 14
, 12, 12 -> 12
)?
The following list ([12, 14, 14, 12, 12, 14]
):
List<string> foo = new List<string> { 12, 14, 14, 12, 12, 14 };
to the list [12, 14, 12, 14]
?
Approach with foreach
public static IEnumerable<T> DistinctByPrevious<T>(List<T> source)
{
if (source != null && source.Any())
{
T prev = source.First();
yield return prev;
foreach (T item in source.Skip(1))
{
if (!EqualityComparer<T>.Default.Equals(item, prev))
{
yield return item;
}
prev = item;
}
}
}
Linq without additional libraries, but with side effects is a quick and dirty (prior
side effect is ugly) solution:
List<string> foo = new List<string> { "12", "14", "14", "12", "12", "14" };
string prior = null;
List<string> result = foo
.Where((v, i) => i == 0 || v != prior)
.Select(v => prior = v)
.ToList();
In general case, you may want to implement an extension method:
public static partial class EnumerableExtensions {
public static IEnumerable<T> DistinctSuccessive<T>(
this IEnumerable<T> source,
IEqualityComparer<T> comparer = null) {
// public method arguments validation
if (null == source)
throw new ArgumentNullException(nameof(source));
// equals: either default or custom one
Func<T, T, bool> equals = (left, right) => null == comparer
? object.Equals(left, right)
: comparer.Equals(left, right);
bool first = true;
T prior = default(T);
foreach (var item in source) {
if (first || !equals(item, prior))
yield return item;
first = false;
prior = item;
}
}
}
Then
List<string> result = foo
.DistinctSuccessive()
.ToList();
I personally prefere @fubo answer, but just to show that there is more variants:
var data = new[] { 12, 14, 14, 12, 12, 14 };
var result = data.Aggregate(new List<int>(), (a, e) => { if (a.FirstOrDefault() != e) a.Insert(0, e); return a; });
result.Reverse(); // we builded a list in a back order, so reverse it!