假设我有这个清单:
int[] list = { 1, 2, 3, 3, 1 };
我想要的是删除紧跟相同号码的重复项。所以在这种情况下我想删除3,但不是1。
因此,新列表应为:{1, 2, 3, 1}
另一个例子是这个列表:{2, 7, 7, 7, 2, 6, 4}
,它将成为{2, 7, 2, 6, 4}
。
我可以使用LINQ吗?
答案 0 :(得分:5)
如果您想使用现有的LINQ方法,可以使用Aggregate
,但这样的方法会失去懒惰。您可以编写自己的扩展方法:
public static IEnumerable<T> RemoveConsecutiveDuplicates<T>(this IEnumerable<T> source, IEqualityComparer<T> comp = null)
{
comp = comp ?? EqualityComparer<T>.Default;
using (var e = source.GetEnumerator())
{
if (e.MoveNext())
{
T last = e.Current;
yield return e.Current;
while (e.MoveNext())
{
if (!comp.Equals(e.Current, last))
{
yield return e.Current;
last = e.Current;
}
}
}
}
}
答案 1 :(得分:3)
如果您坚持使用LINQ执行此操作,则可以使用instance Show (m (Maybe a)) => Show (MaybeT m a)
:
Aggregate
但由于每次迭代中var result = array.Aggregate(new List<int>(), (a, b) =>
{
if (!a.Any() || a.Last() != b)
a.Add(b);
return a;
});
和Any
,这不一定是最有效的解决方案。比较先前和当前迭代值的简单Last
将表现得更好。
答案 2 :(得分:2)
您可以使用MoreLINQ中的PairWise
,如下所示:
var result =
new[] {list[0]}
.Concat(
list
.Pairwise((x, y) => new {Item = y, Same = x == y})
.Where(x => !x.Same)
.Select(x => x.Item))
.ToArray();
PairWise
允许您获得一个序列,该序列源于对原始序列中的每个项目应用函数以及它之前的项目(期望第一个项目)。
我在这里做的是为每个项目(期望第一项),我得到项目本身和布尔值(Same
),指示此项目是否等于它之前的项目。然后,我过滤序列只采取每个不等于它之前的项目的项目。然后,我只是将原始列表中的第一项附加到新序列。
注意:不要忘记处理list
为空的情况。
答案 3 :(得分:1)
您可以执行以下操作(不使用linq)。
var collection = new [] { 2, 7, 7, 7, 2, 6, 4 }.ToList();
for (int i = 0; i < collection.Count - 1; i++)
{
if (collection[i] == collection[i + 1])
{
collection.RemoveAt(i);
i--;
}
}
另一种基于收益率的解决方案就是这样。
public static IEnumerable<T> RemoveConsecutiveDuplicates<T>(this IEnumerable<T> collection)
{
using (var enumerator = collection.GetEnumerator())
{
bool wasNotLast = enumerator.MoveNext(),
hasEntry = wasNotLast;
T last = hasEntry ? enumerator.Current : default(T);
while(wasNotLast)
{
if (!last.Equals(enumerator.Current))
yield return last;
last = enumerator.Current;
wasNotLast = enumerator.MoveNext();
}
if (hasEntry)
yield return last;
}
}