Suppongo che non vuoi utilizzare memoria extra e non voler superare la complessità algoritmica del metodo di iterazione sottostante, quindi ToList, GroupBy, IndexOf non sono consentiti nelle mie implementazioni proposte.
Inoltre, per non mettere vincoli sul tipo di elemento, sto usando predicati.
public static class EnumerableExtensions
{
/// <summary>
/// This one works using existing linq methods.
/// </summary>
public static IEnumerable<T> GetRange<T>(this IEnumerable<T> source, Func<T, bool> isStart, Func<T, bool> isStop)
{
var provideExtraItem = new[] { true, false };
return source
.SkipWhile(i => !isStart(i))
.SelectMany(i => provideExtraItem, (item, useThisOne) => new {item, useThisOne })
.TakeWhile(i => i.useThisOne || !isStop(i.item))
.Where(i => i.useThisOne)
.Select(i => i.item);
}
/// <summary>
/// This one is probably a bit faster.
/// </summary>
public static IEnumerable<T> GetRangeUsingIterator<T>(this IEnumerable<T> source, Func<T, bool> isStart, Func<T, bool> isStop)
{
using (var iterator = source.GetEnumerator())
{
while (iterator.MoveNext())
{
if (isStart(iterator.Current))
{
yield return iterator.Current;
break;
}
}
while (iterator.MoveNext())
{
yield return iterator.Current;
if (isStop(iterator.Current))
break;
}
}
}
}
Questi metodi possono essere usati come metodi di estensione:
new[]{"apple", "orange", "banana", "pineapple"}.GetRange(i => i == "orange", i => i == "banana")
fonte
2015-08-11 11:02:23
no, ma dovrebbe essere facile per creare il proprio. Se chiarisci le tue esigenze su ciò che è accettabile, qualcuno può trovare codice duplicato o suggerito. –
Se si conoscono i due elementi nell'elenco, in questo ordine, utilizzare solo questa query e "Concat" il comando "endElement" fino alla fine.Se non sai se gli elementi ci sono nell'ordine richiesto, dovrai materializzare completamente la parte richiesta della lista prima di restituire anche il primo elemento al chiamante (perché non devi restituire nulla se il 'endElement 'non è in realtà lì, o addirittura lanciare un'eccezione). – GSerg