简体   繁体   English

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

[英]Is this achievable with a single LINQ query?

Suppose I have a given object of type IEnumerable<string> which is the return value of method SomeMethod() , and which contains no repeated elements. 假设我有一个IEnumerable<string>类型的给定对象,它是方法SomeMethod()的返回值,并且不包含重复元素。 I would like to be able to "zip" the following lines in a single LINQ query: 我希望能够在单个LINQ查询中“压缩”以下行:

IEnumerable<string> someList = SomeMethod();

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

Edit: I mistakenly used Single instead of First . 编辑:我错误地使用了Single而不是First Corrected now. 现在更正了。

I know I can "zip" this by using the ternary operator, but that's just not the point. 我知道我可以通过使用三元运算符来“压缩”这个,但这不是重点。 I would just list to be able to achieve this with a single line. 我只是列出能够用一条线实现这一目标。 Is that possible? 那可能吗?

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

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

What is wrong with the ternary operator? 三元运算符有什么问题?

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

It would be better to do the Where followed by the Any but I can't think of how to one-line that. 最好选择Where跟随Any,但我想不出如何单行。

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

return reducedEnumerable.Any() ? reducedEnumerable : someList;

The nature of your desired output requires that you either make two requests for the data, like you are now, or buffer the non-matches to return if no matches are found. 所需输出的性质要求您像现在一样对数据发出两个请求,或者如果没有找到匹配则缓冲非匹配以返回。 The later would be especially useful in cases where actually getting the data is a relatively expensive call (eg: database query or WCF service). 在实际获取数据是相对昂贵的调用(例如:数据库查询或WCF服务)的情况下,后者将特别有用。 The buffering method would look like this: 缓冲方法如下所示:

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

The laziness of this method is either that of Where or ToList depending on if the collection contains a match or not. 此方法的懒惰是WhereToList具体取决于集合是否包含匹配项。 If it does, you should get execution similar to Where . 如果是,您应该执行类似于Where执行。 If not, you will get roughly the execution of calling ToList (with the overhead of all the failed filter checks) and iterating the result. 如果没有,您将大致执行调用ToList的执行(带有所有失败的过滤器检查的开销)并迭代结果。

It is not possible to change the return type on the method, which is what you're asking. 无法更改方法的返回类型,这就是您所要求的。 The first condition returns a string and the second condition returns a collection of strings. 第一个条件返回一个字符串,第二个条件返回一个字符串集合。

Just return the IEnumerable<string> collection, and call Single on the return value like this: 只需返回IEnumerable<string>集合,并在返回值上调用Single ,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM