这可以通过单个LINQ查询实现吗?

时间:2011-10-11 16:26:22

标签: c# linq ienumerable

假设我有一个IEnumerable<string>类型的给定对象,它是方法SomeMethod()的返回值,并且不包含重复的元素。我希望能够在单个LINQ查询中“压缩”以下行:

IEnumerable<string> someList = SomeMethod();

if (someList.Contains(givenString))
{
    return (someList.Where(givenString));
}
else
{
    return (someList);
}

修改:我错误地使用了Single而不是First。现已更正。

我知道我可以通过使用三元运算符来“压缩”这个,但这不是重点。我只是列出能够用一条线实现这一目标。这可能吗?

4 个答案:

答案 0 :(得分:4)

这将返回具有给定字符串的项目或所有项目(如果列表中不存在:

someList.Where(i => i == givenString || !someList.Contains(givenString))

答案 1 :(得分:2)

三元运算符有什么问题?

someList.Any(s => s == givenString) ? someList.Where(s => s == givenString) : someList;

最好选择Any跟随的地方,但我想不出如何一行。

var reducedEnumerable = someList.Where(s => s == givenString);

return reducedEnumerable.Any() ? reducedEnumerable : someList;

答案 2 :(得分:2)

您所需输出的性质要求您像现在一样对数据发出两个请求,或者如果找不到匹配则缓冲非匹配项以返回。在实际获取数据是相对昂贵的调用(例如:数据库查询或WCF服务)的情况下,后者将特别有用。缓冲方法如下所示:

static IEnumerable<T> AllIfNone<T>(this IEnumerable<T> source, 
                                   Func<T, bool> predicate)
{
    //argument checking ignored for sample purposes
    var buffer = new List<T>();
    bool foundFirst = false;
    foreach (var item in source)
    {
        if (predicate(item))
        {
            foundFirst = true;
            yield return item;
        }
        else if (!foundFirst)
        {
            buffer.Add(item);
        }
    }

    if (!foundFirst)
    {
        foreach (var item in buffer)
        {
            yield return item;
        }
    }
}

此方法的懒惰是WhereToList的懒惰,具体取决于集合是否包含匹配项。如果是,则应该执行与Where类似的执行。如果没有,您将大致执行调用ToList的执行(带有所有失败的过滤器检查的开销)并迭代结果。

答案 3 :(得分:0)

无法更改方法的返回类型,这就是您所要求的。第一个条件返回一个字符串,第二个条件返回一个字符串集合。

只需返回IEnumerable<string>集合,然后在返回值上调用Single,如下所示:

string test = ReturnCollectionOfStrings().Single(x => x == "test");