記一次使用 SelectMany 的經歷

業荒於嬉發表於2021-12-02

最近在改造一個功能時為了減少迴圈的層數,於是想著將List列表對映為一個能直接使用顆粒大小的List列表,這樣一層迴圈就可以解決問題。

    public class ConflictWordItemForDisplay
    {
        /// <summary>
        /// 基準欄位
        /// </summary>
        public string BasisField { get; set; }
        /// <summary>
        /// 關鍵字
        /// </summary>
        public string Keyword { get; set; }
        /// <summary>
        /// 衝突詞彙(支援多個詞彙,詞彙之間用,分隔)
        /// </summary>
        public string ConflictWord { get; set; }
        /// <summary>
        /// 判別欄位
        /// </summary>
        public List<string> JudgingFields { get; set; }

    }

定義的資料類類似上面,在實際使用去進行判斷時可能需要用到三層迴圈,類似下面的虛擬碼

            foreach (var item in conflictWordItemForDisplayList)
            {
                if (基準欄位的內容.ToUpper().contains(item.Keyword.ToUpper()))
                {
                    foreach (var judgingField in item.JudgingFields)
                    {
                        foreach (var word in item.ConflictWord.Split(','))
                        {
                            if (judgingField對應的判別欄位的內容.ToUpper().contains(word.ToUpper()))
                            {
                                //衝突,進行對應的處理(提示使用者讓使用者修改之類)
                            }
                        }
                    }
                }
            }

在判別欄位型別較少且固定時可以用判斷邏輯來減少一層迴圈。

如果用 SelectMany將粒度降到最小應該怎麼寫呢。微軟對SelectMany的描述是將序列的每個元素投影到 IEnumerable<T> 並將結果序列合併為一個序列。包括以下過載

 

 

 

將判別欄位降低到最小粒度:

            var allConflictWordItemForDisplay = conflictWordItemForDisplayList.SelectMany(p => p.JudgingFields, (s, r) => new ConflictWordItemForDisplay() { BasisField=s.BasisField,Keyword=s.Keyword,ConflictWord=s.ConflictWord,JudgingFields=new List<string> { r} });

將衝突詞彙降低到單獨一個詞彙的粒度:

allConflictWordItemForDisplay = allConflictWordItemForDisplay.SelectMany(p => p.ConflictWord.Split(','), (s, r) => new ConflictWordItemForDisplay() { BasisField = s.BasisField, Keyword = s.Keyword, ConflictWord = r, JudgingFields = s.JudgingFields });

這只是SelectMany適用於我這個問題的使用方式,SelectMany還有其他過載函式,使用到時可以詳細瞭解一下。

下面是微軟官方文件,裡面也有用例方便理解。

https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.selectmany?view=netframework-4.6.1

 

相關文章