簡體   English   中英

使用Lambda表達式和linq

[英]Using lambda expressions and linq

因此,我剛剛開始使用linq以及使用lambda表達式。 嘗試獲取一些我想要的數據時,我遇到了一個小小的麻煩。 此方法應返回從Jira打開或正在進行的所有項目的列表

這是代碼

    public static List<string> getOpenIssuesListByProject(string _projectName)
    {
        JiraSoapServiceService jiraSoapService = new JiraSoapServiceService();
        string token = jiraSoapService.login(DEFAULT_UN, DEFAULT_PW);
        string[] keys = { getProjectKey(_projectName) };

        RemoteStatus[] statuses = jiraSoapService.getStatuses(token);
        var desiredStatuses = statuses.Where(x => x.name == "Open" || x.name == "In Progress")
            .Select(x=>x.id);

        RemoteIssue[] AllIssues = jiraSoapService.getIssuesFromTextSearchWithProject(token, keys, "", 99);
        IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=>
            {
                foreach (var v in desiredStatuses)
                {
                    if (x.status == v)
                        return true;
                    else
                        return false;
                }
                return false;
            });
        return openIssues.Select(x => x.key).ToList();
    }

現在,這僅選擇“打開”的問題,似乎跳過了“進行中”的問題。

我的問題:首先,為什么我只收到“公開”問題,其次,還有更好的方法嗎?

我首先獲取所有狀態的原因是問題僅存儲了該狀態ID,因此我獲取了所有狀態,獲取了與“打開”和“進行中”匹配的ID,然后將這些ID號與問題狀態字段匹配。

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=>
        {
            foreach (var v in desiredStatuses)
            {
                if (x.status == v)
                    return true;
            }
            return false;
        });

您擁有的代碼僅檢查第一個狀態並返回false。 您需要迭代所有狀態並僅在根本不在列表中時返回false。

好吧,你可以改變

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=>
{
    foreach (var v in desiredStatuses)
    {
        if (x.status == v)
            return true;
        else
            return false;
    }
    return false;
});

IEnumerable<RemoteIssue> openIssues =
      AllIssues.Where(x=> desiredStatuses.Contains(x.status));

至於為什么你沒有同時獲得兩種身份-斯蒂芬回答了。 我上面的代碼更改也將解決該問題。

之所以只得到一個狀態,是因為您總是在第一次檢查后就退出循環。 如果第一個項目不匹配,則不會檢查更多項目。 如果您刪除else中的收益,它將起作用:

foreach (var v in desiredStatuses) {
  if (x.status == v) {
    return true;
  }
}
return false;

您應該確保實現所需狀態的收集,以免您每次使用它時都不會重新運行創建它的查詢:

var desiredStatuses =
  statuses
  .Where(x => x.name == "Open" || x.name == "In Progress")
  .Select(x=>x.id)
  .ToList();

如果您只想檢查幾種狀態,則無需使其效率更高。 如果狀態很多,您可以將狀態實現到HashSet並使用它的Contains方法,該方法比遍歷項目快得多。

該代碼對我來說似乎正確,盡管有許多方法可以減少編寫的代碼。

關於:

現在,這僅選擇“打開”的問題,似乎跳過了“進行中”的問題。

您能否確定兩者都處於期望狀態?

我還假設RemoteIssue.status屬性確實是指狀態的ID,而不是名稱,因為這就是您要與之比較的內容?

然后根據馬丁·哈里斯(Martin Harris)的答案編寫代碼:我將使用Contains運算符,而不是您的內部循環...

更改此:

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=>
            {
                foreach (var v in desiredStatuses)
                {
                    if (x.status == v)
                        return true;
                    else
                        return false;
                }
                return false;
            });

對此:

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=>
            {
                foreach (var v in desiredStatuses)
                {
                    if (x.status == v)
                        return true;
                    //else
                        //return false;
                }
                return false;
            });

其他答案是正確的,但是您可以使用簡單的Lambda而不是匿名委托來更加簡潔地完成此操作。

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=> 
        desiredStatuses.Contains(x.status)

因此,您的整個方法如下所示:

public static List<string> getOpenIssuesListByProject(string _projectName)
{
    JiraSoapServiceService jiraSoapService = new JiraSoapServiceService();
    string token = jiraSoapService.login(DEFAULT_UN, DEFAULT_PW);
    string[] keys = { getProjectKey(_projectName) };

    RemoteStatus[] statuses = jiraSoapService.getStatuses(token);
    var desiredStatuses = statuses.Where(x => x.name == "Open" || x.name == "In Progress")
        .Select(x=>x.id);

    RemoteIssue[] AllIssues = jiraSoapService.getIssuesFromTextSearchWithProject(token, keys, "", 99);
    IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x => desiredStatuses.Contains(x.status));
    return openIssues.Select(x => x.key).ToList();
}

這基本上發出了SQL“ IN”子句的等效項。 因此,您的陳述如下:

SELECT <RemoteIssue> FROM AllIssues AS x WHERE x.status IN <desiredStatuses>

暫無
暫無

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

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