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

本文关键字:查询 实现 LINQ 单个 是否 可以通过 | 更新日期: 2023-09-27 18:10:53

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

IEnumerable<string> someList = SomeMethod();
if (someList.Contains(givenString))
{
    return (someList.Where(givenString));
}
else
{
    return (someList);
}

编辑:我错误地用Single代替First。现在更正。

我知道我可以通过使用三元运算符来"压缩"它,但这不是重点。我只是列出能够实现这一点,用一行。这可能吗?

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

这将返回带有给定字符串的项,如果给定不在列表中,则返回所有项:

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

所需输出的性质要求您对数据发出两个请求,就像现在一样,或者缓冲未找到匹配项时返回的不匹配项。后者在实际获取数据是一个相对昂贵的调用(例如:数据库查询或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的大致执行(包含所有失败的过滤器检查的开销)并迭代结果。

三元运算符有什么问题?

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

最好在Where后面加上Any,但是我想不出如何一行。

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

改变方法的返回类型是不可能的,这就是你所要求的。第一个条件返回一个字符串,第二个条件返回一个字符串集合。

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

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