簡體   English   中英

使用linq從字符串拆分中獲取倒數第二個元素

[英]Get the next to last element from a string split using linq

我有一個字符串(folderpath),並用一個字符(\\)將其分割,該字符產生並排列了子字符串(單個文件夾)。 如何在一行LINQ查詢中從中獲取最后一個文件夾。

基本上將下面的內容轉換為單行LINQ查詢。

var test = item.Split('\\');
var count = test.Length;
var folder = test[count - 2];

我對如何獲取數組的計數然后在一行中指定count -2感到困惑。

我在這里看不到使用LINQ的任何好處,但是這里有:

item.Split('\\').Reverse().Skip(1).First();

由於反轉,這將比您現有的代碼執行得差。

開箱即用,LINQ沒有執行此操作的方法,您可以編寫自己的擴展方法以執行類似的操作,但請查看Last()的源代碼-這是您嘗試實現的最接近的方法-實際上它所做的事情與您正在做的事情非常相似:

        int count = list.Count;
        if (count > 0) return list[count - 1];

因此,在幕后沒有魔力發生,我認為,您應該只保留已經擁有的代碼,就像需要的那樣,並且清晰易懂,而不是創建不必要的擴展方法或復雜的代碼LINQ查詢

讓我們用這個答案來學習完整的熱核,只是為了好玩。 我們可以使用LINQ創建性能與您的解決方案相媲美的單行查詢,但是我們必須首先創建幾個擴展方法。

Split的問題在於它返回一個string[]而我們真正需要的是IEnumerable<string> 是的,所有string[]都是IEnumerabl<string>但並非所有IEnumerable<string>都是string[] -我們真正​​感興趣的是惰性求值,而我們不會通過Split獲得它。 因此,讓我們自己動手吧!

public static class StringExtensions
{
    public static IEnumerable<string> SplitAsEnumerable(this string source, char splitter)
    {
        if (source == null)
        {
            yield break;
        }

        var builder = new StringBuilder();

        foreach (char c in source)
        {
            if (c != splitter)
            {
                builder.Append(c);
            }
            else
            {
                if (builder.Length > 0)
                {
                    yield return builder.ToString();
                    builder.Clear();
                }
            }
        }
    }
}

您可以隨心所欲地為此瘋狂。 添加重載以接受char[]stringstring[]來分割您的字符串。 動用你的想象力。

現在這是一個很好的第一步,但是我們需要一些東西來允許我們使用IEnumerable的最后一個元素。 交互式擴展提供了TakeLast擴展方法,但是我們不希望沒有討厭的依賴關系,所以讓我們開始吧!

public static class EnumerableExtensions
{
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int count)
    {
        var queue = new Queue<T>(count);
        if (source == null)
        {
            yield break;
        }
        foreach (var item in source)
        {
            if (queue.Count == count)
            {
                queue.Dequeue();
            }
            queue.Enqueue(item);
        }
        foreach (var item in queue)
        {
            yield return item;
        }
    }
}

現在,我們可以根據需要刪除盡可能多的元素。

上面的擴展方法看起來很棒! 我確信可以進行一些優化,當然我們需要注意一些極端情況,但這對於我們開始來說已經足夠了。

現在,我們可以使用擴展方法和LINQ。 開始了:

var folder = item.SplitAsEnumerable('\\').TakeLast(2).FirstOrDefault();

到這里-您選擇了倒數第二個子字符串,其運行時間為O(n),與您現有的解決方案相當,並且(可能)更好的空間復雜度,因為我們正在使用的Queue可能比Split返回的數組小(這取決於傳遞給TakeLastcount )。

暫無
暫無

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

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