You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否存在等效于Unix命令uniq的Linq实现?Distinct()不符合需求

移除连续重复项的LINQ实现方案

当然可以用LINQ实现这个需求!你提到的Distinct()方法确实是全局去重,会移除所有重复的元素,不管它们是不是连续的——这显然不符合你只移除连续重复项的要求。不过我们可以通过自定义Enumerable扩展方法,或者直接使用Aggregate来实现这个功能。

方法一:自定义扩展方法(推荐,复用性强)

我们可以写一个通用的扩展方法,专门用来过滤序列中的连续重复元素,这样以后任何序列都能直接调用:

public static class EnumerableExtensions
{
    public static IEnumerable<T> RemoveConsecutiveDuplicates<T>(this IEnumerable<T> source)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source));
        
        using var enumerator = source.GetEnumerator();
        if (!enumerator.MoveNext())
            yield break;
        
        var previous = enumerator.Current;
        yield return previous;
        
        while (enumerator.MoveNext())
        {
            var current = enumerator.Current;
            if (!EqualityComparer<T>.Default.Equals(current, previous))
            {
                yield return current;
                previous = current;
            }
        }
    }
}

使用示例(匹配你的需求)

int[] input = new [] {1,2,3,3,4,5,5,5,6,6,5,4,4,3,2,1,6};
int[] expected = new [] {1,2,3,4,5,6,5,4,3,2,1,6};

var result = input.RemoveConsecutiveDuplicates().ToArray();
// 此时result和expected完全一致

这个方法的逻辑很清晰:

  • 先检查输入序列是否为空,避免空引用异常
  • 获取序列的枚举器,先取出第一个元素并返回
  • 遍历后续元素,只有当当前元素和前一个元素不相等时,才返回该元素,并更新“前一个元素”的引用

方法二:直接使用Aggregate(无需扩展方法)

如果你不想写扩展方法,也可以用Aggregate来一次性处理:

int[] input = new [] {1,2,3,3,4,5,5,5,6,6,5,4,4,3,2,1,6};

var result = input.Aggregate(new List<int>(), (list, current) =>
{
    if (list.Count == 0 || list.Last() != current)
        list.Add(current);
    return list;
}).ToArray();

这个方式会逐步构建结果列表:每次添加元素前,检查列表最后一个元素是否和当前元素相同,不同才添加。不过相比扩展方法,它需要提前创建列表,对于非常大的序列,内存占用会高一些——扩展方法用的是延迟执行,更高效。

两种方法都能完美满足你的需求,输出结果和你给出的expected数组完全一致。

内容的提问来源于stack exchange,提问作者Rachel Davids

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:56:55