Linq是否与unix命令uniq

时间:2018-04-05 06:56:19

标签: c# linq ienumerable uniq

我所做的每一次搜索都假定为“Distinct()”,但这不是我的要求。我只想删除所有重复。是否有使用linq的选项(即可枚举扩展名)?

例如(在C#中)

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};

2 个答案:

答案 0 :(得分:2)

有可能使用linq,虽然为了性能和可读性,一个简单的for循环可能是更好的选择。

int[] input = new[] { 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 5, 4, 4, 3, 2, 1, 6 };
var result = input.Where((x, i) => i == 0 || x != input[i - 1]).ToArray();

答案 1 :(得分:2)

您要求的是非重复元素,而不是唯一元素。 LINQ-to-Objects操作本质上是迭代器。您可以编写自己的迭代器方法,该方法仅在第一次遇到项时产生,例如:

public static IEnumerable<int> DistinctUntilChanged(this IEnumerable<int> source)
{
    int? previous=null;
    foreach(var item in source)
    {
        if (item!=previous)
        {
            previous=item;
            yield return item;
        }
    }
}

var input = new [] {1,2,3,3,4,5,5,5,6,6,5,4,4,3,2,1,6};
var result=input.DistinctUntilChanged().ToArray();

结果将是:

{1,2,3,4,5,6,5,4,3,2,1,6};

<强>更新

另一种选择是使用System.Reactive Library中的Observable.DistinctUntilChanged,例如:

var input = new[] { 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 5, 4, 4, 3, 2, 1, 6 };
var result = input.ToObservable()
                  .DistinctUntilChanged()
                  .ToEnumerable()
                  .ToArray();

System.Reactive和Reactive Extensions旨在使用基本的LINQ运算符处理事件序列等。使用ToObservable()ToEnumerable()可以很容易地在Observable和Enumerable之间进行转换,因此它们可以用于处理任何集合。毕竟,事件序列类似于“无限”序列

更新2

如果对使用int?存储前一个数字感到困惑,那么即使与源的第一个元素进行简单比较也不会实际调用{{1} } 在上面。如果是,例如First()且第一个元素为0,则比较将过滤掉第一个元素。

使用C#中的int previous=0;或F#中的int?int option如果我们有一个可能的monad,我们可以区分无初始值和初始值0。 / p>

Observable.DistinctUntilChanged使用一个标志来检查我们是否正在检查第一个元素。等效代码为:

Maybe<int>

<强> MoreLINQ

最后,可以使用MoreLinq库中的GroupAdjacent方法将重复项组合在一起。每个组包含重复的源元素。在这种特殊情况下,我们只需要键值:

    public static IEnumerable<int> NonRepeating(this IEnumerable<int> source)
    {
        int previous =0;
        bool isAssigned=false;
        foreach (var item in source)
        {
            if (!isAssigned || item != previous)
            {
                isAssigned = true;
                previous = item;
                yield return item;
            }
        }
    }

关于var result = input.GroupAdjacent(i => i).Select(i => i.Key).ToArray(); 的好处是元素可以在分组时进行转换,例如:

GroupAdjacent

将返回字符串分组。