C#:SkipLast实施
-
13-09-2019 - |
题
我需要一种方法来给我所有,但最后一个项目中的序列。这是我目前的实现:
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if(iterator.MoveNext())
while(true)
{
var current = iterator.Current;
if(!iterator.MoveNext())
yield break;
yield return current;
}
}
}
我需要它是做一些与除了最后一个所有项目。在我来说,我有不同的属性的对象的序列。然后我按日期排序他们,然后我需要做一个调整,所有的人,除了最近的项目(这将是订货后最后一个)。
事情是,我不是太为这些普查员和东西却和真的没有人在这里问任:对我想知道是,如果这是一个很好的实现,或者,如果我做了一个小或大跌跌撞撞的地方。或者,如果这也许就该问题是一个奇怪的一个,等等。
我想的更一般的实施可能是一个AllExceptMaxBy
方法。因为这是一种什么了。该 MoreLinq 有MaxBy
和MinBy
方法和我的方法种类需要做的相同的,但返回的每一项除了最大值或最小值之一。
解决方案
这是棘手的,因为“最后一个元素”是不是一个马尔科夫停止点:你不能告诉你已经到了最后一个元素,直到你试图让下一个。这是可行的,但前提是你不会永久被“背后一个元素”介意。这基本上是你当前的实现做什么,它看起来不错,但我可能会写略有不同。
另一种方法将是使用foreach
,总是得到先前返回的值,除非你在第一次迭代:
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
T previous = default(T);
bool first = true;
foreach (T element in source)
{
if (!first)
{
yield return previous;
}
previous = element;
first = false;
}
}
另一种选择,更接近您的代码:
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if(!iterator.MoveNext())
{
yield break;
}
T previous = iterator.Current;
while (iterator.MoveNext())
{
yield return previous;
previous = iterator.Current;
}
}
}
这避免了嵌套相当深深(由如果序列是空做提前退出),它使用一个“真正的”,而条件代替while(true)
其他提示
您实现看起来完全没有给我 - 它可能是我会做的方式
我可能会就你的情况建议唯一的简化是对列表进行排序的的另一种方式圆的(即上升,而不是下降)。虽然这可能不适合在你的代码,这将让你简单地使用collection.Skip(1)
采取的所有项目,除了最近的一个。
如果这是不可能的,你有没有在您的文章中所示的原因,那么你目前的实现是没有问题的。
如果您正在使用.net 3.5,我想你可以使用:
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
return source.TakeWhile((item, index) => index < source.Count() - 1))
}
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
if (!source.Any())
{
yield break;
}
Queue<T> items = new Queue<T>();
items.Enqueue(source.First());
foreach(T item in source.Skip(1))
{
yield return items.Dequeue();
items.Enqueue(item);
}
}
(旧答案报废;此代码已被测试和工程)它打印结果 首先点击 第二个结果 FIRST结果 SECOND结果 THIRD
public static class ExtNum{
public static IEnumerable skipLast(this IEnumerable source){
if ( ! source.Any())
yield break;
for (int i = 0 ; i <=source.Count()-2 ; i++ )
yield return source.ElementAt(i);
yield break;
}
}
class Program
{
static void Main( string[] args )
{
Queue qq = new Queue();
qq.Enqueue("first");qq.Enqueue("second");qq.Enqueue("third");
List lq = new List();
lq.Add("FIRST"); lq.Add("SECOND"); lq.Add("THIRD"); lq.Add("FOURTH");
foreach(string s1 in qq.skipLast())
Console.WriteLine(s1);
foreach ( string s2 in lq.skipLast())
Console.WriteLine(s2);
}
}