假设我有一个IEnumerable<string>
类型的给定对象,它是方法SomeMethod()
的返回值,并且不包含重复的元素。我希望能够在单个LINQ查询中“压缩”以下行:
IEnumerable<string> someList = SomeMethod();
if (someList.Contains(givenString))
{
return (someList.Where(givenString));
}
else
{
return (someList);
}
修改:我错误地使用了Single
而不是First
。现已更正。
我知道我可以通过使用三元运算符来“压缩”这个,但这不是重点。我只是列出能够用一条线实现这一目标。这可能吗?
答案 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;
}
}
}
此方法的懒惰是Where
或ToList
的懒惰,具体取决于集合是否包含匹配项。如果是,则应该执行与Where
类似的执行。如果没有,您将大致执行调用ToList
的执行(带有所有失败的过滤器检查的开销)并迭代结果。
答案 3 :(得分:0)
无法更改方法的返回类型,这就是您所要求的。第一个条件返回一个字符串,第二个条件返回一个字符串集合。
只需返回IEnumerable<string>
集合,然后在返回值上调用Single
,如下所示:
string test = ReturnCollectionOfStrings().Single(x => x == "test");