我想通過一個IEnumerable來檢查重復的內容,并按順序將其洗掉,比如。 一個接收IEnumerable并回傳IEnumerable的方法,并過濾掉像例子中的雙數。 AAABBAACCC變成ABAC 為了達到這個目的,我需要一個方法來查詢IEnumerable,并將每個專案與下一個專案進行比較,如果它們不同,則將它們添加到一個新的IEnumerable中并回傳,或者將每個專案與下一個專案進行比較,如果它們相同則洗掉第一個專案。 我想出了這樣的方法:
public static IEnumerable< T> UniqueInOrder<T>(IEnumerable< T> iterable)
{
var query = from c in iterable
where c != c.Next
select c;
return query;
問題是,c.Next不存在。有什么方法可以做到這一點嗎?或者在Linq中是不可能的?
uj5u.com熱心網友回復:
你可以在LINQ中使用一種方法來 "獲得下一個東西",那就是Zip。具體來說,你可以用同樣的enumerableZip,但是跳過第一個元素。
你的查詢將翻譯成:
public static IEnumerable< T> UniqueInOrder<T>(IEnumerable< T> iterable)
=> iterable.Zip(iterable.Skip(1)).Where(x => !x.First.Equals(x.Second)).Select(x => x.First)。
然而,你這里的邏輯是有缺陷的。AAABBAACCC "的輸出是 "ABA",因為最后一個 "組 "沒有 "下一個 "東西是不同的。如果你將T限制為所有的參考型別,你可以在iterable.Skip(1)的最后添加一個null:
public static IEnumerable<。 T> UniqueInOrder<T>(IEnumerable< T> iterable)
whereT: class
=> iterable.Zip(iterable.Skip(1).Append(null)
.Where(x => !x.First.Equals(x.Second)).Select(x => x.First)。
這樣做的原因是沒有任何東西Equalsnull,因此保證了始終保持最后的 "組"。
我將作為一個回圈來做,檢查前一個專案。
public static IEnumerable< T> UniqueInOrder<T>(IEnumerable< T> iterable){
if (! iterable.Any()) {
yield break;
}
T lastSeen = iterable.First();
yield return lastSeen;
foreach (var t in iterable) {
if (!lastSeen.Equals(t)) {
yield return t。
}
lastSeen = t;
}
旁注:你不能使用!=與一個無約束的通用引數T,所以我把它改為!Equals,但請記住,這不會與nulls一起作業。
uj5u.com熱心網友回復:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program public static void Main()
{
var items = new List<string> (){"A","A","A","B"。 "A","A","C","C"};
foreach(var item in UniqueInOrder(items))
{
Console.Write("{0}"/span>, item)。
}
Console.WriteLine()。
// Oder
foreach(var item in UniqueInOrderLinq(items))
{
Console.Write("{0}"/span>, item)。
}
Console.WriteLine()。
}
public static IEnumerable<T>。UniqueInOrder<T>(IEnumerable<T> input ) where T: IEquatable<T>/span>
{
if( input is null) throw new ArgumentNullException(nameeof(input))。
T prev = input.First();
yield return prev;
foreach( T item in input.Skip(1 ) )
{
if(! item.Equals(prev))
{
yield return item;
prev = item;
}
}
}
public static IEnumerable<T> UniqueInOrderLinq<T>( IEnumerable<T> input ) where T: IEquatable<T>/span>
{
if( input is null) throw new ArgumentNullException(nameof(input))。
return input.Aggregate( new List<T>(), (acc, next) => {if(!acc.LastOrDefault()?.Equals(Next) ? true) {acc.Add(next);} return acc; });
}
來自@Fildor的回答。謝謝你,伙計,效果很好!
uj5u.com熱心網友回復:
為了改進你現有的答案,我們可以在不多次查詢原始碼的情況下這樣做:
public static IEnumerable< T> UniqueInOrder<T>(IEnumerable<T> input, IEqualityComparer<T> comparer = null)。
{
if(input is null) throw new ArgumentNullException(nameof(input)) 。
comparer = comparer ? EqualityComparer<T>.默認。
var isFirst = true;
T prev = default;
foreach( T item in input)
{
if(isFirst)
{
yield return item;
prev = item;
isFirst = false;
}
else if(! comparer.Equals(item, prev))
{
yield return item;
prev = item。
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/310118.html
標籤:
