C# 扩展ienumerable方法C
我写了跳过最后一个方法。当我用int数组调用它时,我希望只返回2个元素,而不是4个 怎么了 谢谢C# 扩展ienumerable方法C,c#,C#,我写了跳过最后一个方法。当我用int数组调用它时,我希望只返回2个元素,而不是4个 怎么了 谢谢 public static class myclass { public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n) { return source.Reverse().Skip(n).Reverse(); } } class
public static class myclass
{
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
return source.Reverse().Skip(n).Reverse();
}
}
class Program
{
static void Main(string[] args)
{
int [] a = new int[] {5, 6, 7, 8};
ArrayList a1 = new ArrayList();
a.SkipLast(2);
for( int i = 0; i <a.Length; i++)
{
Console.Write(a[i]);
}
}
}
你需要打电话给我
var newlist = a.SkipLast(2);
for( int i = 0; i <newlist.Count; i++)
{
Console.Write(newlist[i]);
}
您的方法将返回跳过的列表,但原始列表将不会更新
如果要分配或更新相同的列表,可以将返回的列表设置回原始状态,即a=a.SkipLast2.ToArray 您应该分配结果,而不仅仅是放置a.SkipLast2:
将代码更改为
foreach (var r in a.SkipLast(2))
{
Console.Write(r);
}
原因有三,
SkipLast函数返回变异序列,它不会直接更改它。
将索引器与IEnumerable一起使用有什么意义?它强加了一个不必要的计数。
此代码易于阅读、易于键入并显示意图。
有关更有效的通用SkipLast,请参见
您的示例可以使用更专业的SkipLast
其他回答已经回答了您的问题,但更有效的实现不是这样的吗?它不需要制作两个数组副本以将其反转两次。它会迭代集合两次,或者更确切地说,一次,然后计数n次访问:
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
n = source.Count() - n;
return source.TakeWhile(_ => n-- > 0);
}
您应该添加.ToArray。您不应该访问该for循环中的newList吗?如果我不想用任何其他int数组调用它怎么办。@user1048791:use-foreach;我写了a=a.SkipLast2.ToArray;只是为了保持你的for循环完好无损。通常的方法是在使用LINQ时放置foreach循环-请参阅ASN中我的建议,ArrayList的作用是什么?这里不使用它,这是一件好事。唯一的问题是,IEnumerable不需要证明它可以被枚举两次。在给出的具体示例中,数组显然可以被多次枚举,但这并不是IEnumerable的每个实现都是如此。@Jodrell是的,但这样的枚举总是需要特殊处理。您不希望将其用于Directory.EnumerateDirectory,例如:@JeppeStigNielsen是的,正如我上面所说的,其他回答就是答案。这个回复只是一个注释,但显然我不能用普通的注释编写格式化代码!我的答案是尽量避免复制潜在的大数据,所以按照您的建议执行source.ToArray是我明确希望避免的事情!顺便说一句,我喜欢你最新添加的n长度缓冲区@我的另一个建议避免了你提出的问题。
foreach (var r in a.SkipLast(2))
{
Console.Write(r);
}
public static IEnumerable<T> SkipLast<T>(this IList<T> source, int n = 1)
{
for (var i = 0; i < (source.Count - n); i++)
{
yield return source[i];
}
}
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
n = source.Count() - n;
return source.TakeWhile(_ => n-- > 0);
}
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
int count = 0;
T[] buffer = new T[n];
var iter = source.GetEnumerator();
while (iter.MoveNext())
{
if (count >= n)
yield return buffer[count%n];
buffer[count++%n] = iter.Current;
}
}