Is this possible with a single LINQ query?

Suppose I have a given object of type IEnumerable<string> , which is the return value of the SomeMethod() method and which does not contain duplicate elements. I would like to be able to "zip" the following lines in a single LINQ query:

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

Edit: I mistakenly used Single instead of First . Fixed now.

I know I can “zip up” it using the ternary operator, but that's just not the point. I would just list to achieve this with a single line. Is it possible?

+4
source share
4 answers

The nature of your desired result requires that you either make two requests for data, for example, you are now, or buffer non-matches in order to return if no matches are found. A later version will be especially useful in cases where actually obtaining data is a relatively expensive call (for example: querying a database or WCF service). The buffering method will 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 Where or ToList , depending on whether the collection contains a match or not. If so, you should do a run like Where . If not, you will get roughly executing a ToList call (with the overhead of all failed filter checks) and iterating the result.

+2
source

This will return items with the given string or all items if they are listed:

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

What is wrong with the ternary operator?

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

It would be better to use Where followed by Any, but I can't figure out how to do this on one line.

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

It is not possible to change the type of return method you are requesting. The first condition returns a string, and the second condition returns a set of strings.

Just return the IEnumerable<string> collection and call Single on the return value, like this:

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

All Articles