我所做的每一次搜索都假定为“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};
答案 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
将返回字符串分组。