簡體   English   中英

擴展無數方法C#

[英]extending ienumerable method 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 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.SkipLast(2).ToArray();

您應該分配結果 ,而不僅僅是a.SkipLast(2)

  a = a.SkipLast(2).ToArray(); // <- if you want to change "a" and loop on a 

  for( int i = 0; i <a.Length; i++) { ...

當您執行a.SkipLast(2)它將創建IEnumerable<int> ,然后丟棄 最易讀的解決方案,恕我直言,是使用foreach ,這對於LINQ非常方便:

  ...
  int [] a = new int[] {5, 6, 7, 8};

  foreach(int item in a.SkipLast(2)) 
    Console.Write(item);

將您的代碼更改為

foreach (var r in a.SkipLast(2))
{
    Console.Write(r);
}

出於三個原因,

  1. SkipLast函數返回突變的序列,它不會直接對其進行更改。
  2. IEnumerable中使用索引器有什么意義? 它強加了不必要的計數。
  3. 該代碼易於閱讀,易於鍵入並顯示意圖。

有關更有效的通用SkipLast請參閱帶有枚舉器的Matthew緩沖區。


您的示例可以使用更專業的SkipLast

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];
    }
}

其他答復已經回答了您的問題,但是這樣做不是更有效的實現(它不涉及制作數組的兩個副本以將其反轉兩次)。 它將迭代兩次(或一次,然后進行count-n次訪問):

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
    n = source.Count() - n;
    return source.TakeWhile(_ => n-- > 0);
}

實際上,如果source是無需迭代即可實現Count的類型(例如數組或List),則它將僅訪問count-n次元素,因此對於這些類型而言,這將非常高效。

這是一個更好的解決方案,它只將序列重復一次。 數據要求如此,它只需要一個包含n元素的緩沖區,如果n與序列的大小相比很小,這將非常有效:

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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM