0

所以我刚刚开始使用 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,因此我获取所有状态,获取匹配“Open”和“In Progress”的 ID,然后将这些 ID 号与问题状态字段匹配.

4

6 回答 6

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

您拥有的代码只是检查第一个状态并返回 false。只有当它根本不在列表中时,您才需要迭代所有状态并返回 false。

于 2010-05-19T16:32:04.673 回答
2

嗯,你可以改变

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

至于为什么你没有同时获得这两种状态——斯蒂芬已经回答了这个问题。我上面的代码更改也将解决该问题。

于 2010-05-19T16:30:16.863 回答
1

您只获得一个状态的原因是,您总是在第一次检查后退出循环。如果第一项不匹配,则不再检查其他项。如果您删除 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();

如果您只想检查几个状态,则无需使其更有效。如果有很多状态,您可以将状态实现为 aHashSet并使用它的Contains方法,这比遍历项目快得多。

于 2010-05-19T16:33:59.273 回答
0

代码在我看来是正确的,尽管有一些方法可以用更少的编写代码来做到这一点......

关于:

现在,这只选择“打开”的问题,似乎跳过了“进行中”的问题。

你能确认两者都在desiredStatuses中吗?

另外我假设 RemoteIssue.status 属性确实是指状态的 id 而不是名称,因为这就是您要比较的?

然后对于代码,根据马丁哈里斯的回答:我会使用包含运算符而不是你的内部循环......

于 2010-05-19T16:34:20.553 回答
0

改变这个:

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;
            });
于 2010-05-19T16:38:51.227 回答
0

其他答案是正确的,但是您可以使用直接 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>
于 2010-05-19T17:36:46.970 回答