下面是一個相對簡單的擴展方法,它的來源序列,並告訴任何兩個元素是否被視爲相等的功能,並返回元素的一個序列:
public static IEnumerable<T> Consecutives<T>(this IEnumerable<T> source,
Func<T, T, bool> equals)
{
T last = default(T);
bool first = true;
bool returnedLast = false;
foreach (T current in source)
{
if (!first && equals(current, last))
{
if (!returnedLast)
yield return last;
returnedLast = true;
yield return current;
}
else
returnedLast = false;
first = false;
last = current;
}
}
如果用
嘗試
var sequence = new[] { 3, 4, 7, 8, 9, 2, 4, 6, 0, 1, 1, 17, 2, 3, 2, 20 };
var subsequences = sequence.Consecutives((x, y) => x % 2 == y % 2);
你將得到: 2 4 6 0 1 1 17 2 20
如果你的序列不具有任何重複,T他雷蒙德的解決方案的擴展是效率低下,而且很簡單:
public static IEnumerable<T> Consecutives<T>(this IEnumerable<T> source,
Func<T, T, bool> equals)
{
return source.Zip(source.Skip(1), (x, y) => new[] { x, y })
.Where(d => equals(d[0], d[1]))
.SelectMany(d => d)
.Distinct();
}
哇。你的「簡單」的定義顯然與我的完全不同! – Gabe
不要將長度與非簡單混爲一談。這個算法*很簡單。從序列中讀取,跟蹤當前的「投影」(我稱它爲resultOfCurrentSequence)。對於你遇到的相同投影的每個後續項目,將它添加到當前的子序列(我稱它爲「currentSequence」)。當遇到不同的東西時,如果長度超過一個,則產生當前的子序列,開始一個新的子序列並用新的投影替換舊的投影。如果到達序列的末尾,並且當前子序列的長度不止一個,則將其退回。 – jason
我不是說你的*算法不簡單,只是代碼不是(我不是說你的代碼有什麼問題)。在22行中,它包含了對構造函數,方法和屬性的14次調用,加上4個'if's和'while' - 這就忽略了缺少'using'來處理枚舉數。而且,返回一系列序列並不像返回一個平坦序列那麼簡單。我的解決方案縮短了幾行,沒有構造函數/方法/屬性調用,但它仍然不是我認爲的「簡單」。 – Gabe