簡體   English   中英

如何在LINQ中執行2次檢查

[英]How to perform 2 checks in LINQ Where

public List<SavedOption> GetValidSavedOptions(
    List<Option> itemOptions, 
    List<SavedOption> savedOptions)
{
    List<SavedOption> finalSavedOptions = savedOptions.Where(x => 
        OptionTextDoesMatch(y, x) && 
        itemOptions.Any(y => y.SomeID == x.SomeID)
    ).ToList(); 
}

我對LINQ和Lambdas完全陌生。

在上面的,我需要/想要做的是包括SavedOption只有當該呼叫OptionTextDoesMatchSomeID中的savedOption中的列表中找到SomeIDitemOptions 如果對OptionTextDoesMatch的調用返回true ,並且在itemOption集合中找到了當前的savedOptions SavedOption.SomeID ,則它將位於ToList()

更新:

我試過了,但是語法仍然對我不起作用:

savedOptions.Where(itemOptions.Any(OptionTextDoesMatch(x,y)&&(y => y.SomeID == x.SomeID)))。ToList();

現在我不知道我是否可以像這樣扔x。 我假設如果我這樣做將代表當前的saveOption,並且我不需要=>?

盡管以上答案是正確的 ,但它們是“給人一條魚”的答案。 最好借此機會學習如何將問題分解成小塊,然后將結果重新組合成查詢。

在上面,僅當在itemOptions的SomeID列表中找到對OptionTextDoesMatch和saveOption的SomeID的調用時,我需要/想要做的就是包括SavedOption。

讓我嘗試改寫這個令人困惑的句子。

您有一個SavedOptions列表。 每個SavedOption都有一個ID和一些文本。

您有一個選項列表。 每個選項都有一個ID和一些文本。

您希望過濾SavedOptions列表,以獲取與文本和ID上的某些Option匹配的SavedOptions。

解決問題。 假設您沒有一系列SavedOptions。 假設您只有一個SavedOption和一個Options列表。 你怎么知道這是不是一場比賽?

很簡單:

SavedOption mySavedOption = whatever;
bool matchExists = itemOptions.Any(item=>
    OptionTextDoesMatch(item, mySavedOption) && 
    item.SomeID == mySavedOption.SomeID);

那有意義嗎?

現在假設您要從需要SavedOption的謂詞中得出一個謂詞 你會怎么做? 很簡單:

Func<SavedOption, bool> predicate = savedOption => 
    itemOptions.Any(item=>
        OptionTextDoesMatch(item, savedOption ) && 
        item.SomeID == savedOption.SomeID);

這是確定單個項目是否匹配的謂詞

還有意義嗎? 如果有什么令人困惑的地方,請阻止我。

因此,要對其進行過濾, 請將謂詞應用於已保存選項列表中的每個項目

result = savedOptions.Where(savedOption => 
    itemOptions.Any(item=>
        OptionTextDoesMatch(item, savedOption) && 
        item.SomeID == savedOption.SomeID));

或者,以查詢理解形式,我個人覺得更容易閱讀。

result = from savedOption in savedOptions
         where itemOptions.Any(item =>
             OptionTextDoesMatch(item, savedOption) && 
             item.SomeID == savedOption.SomeID)
         select savedOption;

但是可能更好的選擇是使用聯接。 聯接只是對與一個ID相關的兩個集合的笛卡爾積的過濾器的優化。

result = from savedOption in savedOptions
         join itemOption in itemOptions 
         on savedOption.SomeID equals itemOption.SomeID
         where OptionTextDoesMatch(itemOption, savedOption)
         select savedOption;

明白了嗎?

隨機猜測:

List<SavedOption> finalSavedOptions = savedOptions.Where(x => 
    itemOptions.Any(y => OptionTextDoesMatch(y, x) && y.SomeID == x.SomeID)
).ToList(); 

在Where子句中,您要像使用以下方法一樣,在saveOptions方法中迭代每個對象:

foreach(SavedOption x in savedOptions)
{
    if (OptionTextDoesMatch(y, x)) //y is not yet specified...
    {
        foreach(Option y in itemOptions)
        {
            if (y.SomeID == x.SomeID)
                yield return x;
        }
    }
}

在您的語句中, where子句將迭代您的savedOptions列表,並且對於每次迭代,將saveOption的當前實例分配為'x'。 然后,您要檢查'x'的文本是否與您尚未指定的內容-'y'相匹配。

然后,您進行第二次迭代: itemOptions.Any(y => y.SomeID == x.SomeID) 在這里,您已經指定了y ,現在將其定義為Option的實例,方法與外部lambda表達式相同:

foreach(Option y in itemOptions)
{
    return y.SomeID == x.SomeID;
}

因為x是由外部子句指定的,所以我們可以在內部子句中訪問它,但事實並非如此。 在內部子句中才指定y ,因此您的where子句不起作用。

為了全面診斷您要執行的操作,我需要了解Option和SavedOptions對象的外觀,並弄清楚您在邏輯上要執行的操作,以便准確解釋您的lambda應該如何執行看...

我懷疑您真正想做的事情是這樣的:

foreach(SavedOption x in savedOptions)
    foreach(Option y in itemOptions)
        if (OptionTextDoesMatch(y, x) && (y.SomeID == x.SomeID))
            yield return x;

用lambda表示的將是:

return savedOptions.Where(x => itemOptions.Any(y => OptionTextDoesMatch(y, x) && (y.SomeID == x.SomeID)));

暫無
暫無

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

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