我尝试获取IEnumerable的值,我需要修改Select的默认返回值并需要丢弃空值。
在此函数中,我为此“ .Elements()”使用XElement对象。
我需要此功能具有最佳性能,因此我在代码中使用bar
。
Select(x => { }..)
基本的“问题”是当我创建此代码时,我的结果是:
IE大量内容:
.Select(versiones =>
{
var last= versiones.Elements().Last();
if (last.condition)
{
var foo = bar(last);
return new
{
Last = last,
Foo = foo
};
}
return null; // i need change it
})
我需要用它来明确:
0[{Last=...,Foo=...}]
1 null
2 null
3 null
4 null
5[{Last=...,Foo=...}]
...
或
.Where(element=> element != null)
不是最好的选择,不像我的ienum中的另一个循环。
我想返回:
.RemoveAll(null)
答案 0 :(得分:2)
基本问题是,当应使用Select
时,您正在使用Where
来过滤元素。由于您在调用null
之前不知道哪些元素可能是Select
,因此最好使用:
.Select(...)
.Where(x => x != null);
请注意,与第二个示例使用RemoveAll
不同,在Where
内运行的过滤器将在与Select
调用相同的循环中求值。
答案 1 :(得分:1)
实际上,您不需要。无论如何,集合中只有一个遍历。
为什么?
因为LINQ表达式惰性;实际上,以下代码
var l = ...;
var l2 = l.Select(i => i.ToString()).Where(i => !string.IsNullOrEmpty(i));
甚至一次都不会遍历数组!
每个LINQ运算符都返回一个IEnumerable<T>
,该迭代器仅在对其进行迭代时才检索其结果。除了以下三种情况:
1)使用返回特殊集合(List<T>
,数组)的LINQ运算符。例如ToList()
,ToArray()
等
2)对结果执行foreach
循环,然后在请求每个项目时对其进行检索。
3)使用计数或总和运算符(仅返回一个结果的运算符),例如Count()
,Average()
,Aggerate()
等。
要了解其工作原理,让我们看看Select()
的可选实现:
public IEnumerable<TOutput> Select<TInput, TOutput>(this IEnumerable<TInput> source, Func<TInput, TOutput> selector)
{
return new SelectEnumerable(source, selector);
}
神奇的事物发生在SelectEnumerable
类中:
private class SelectEnumerable<TInput, TOutput> : IEnumerable<TOutput>
{
private readonly IEnumerable<TInput> _Source;
private readonly Func<TInput, TOutput> _Selector;
public SelectEnumerable(IEnumerable<TInput> source, Func<TInput, TOutput> selector)
{
this._Source = source;
this._Selector = selector;
}
public IEnumerator<TOutput> GetEnumerator()
{
foreach (TInput item in _Source)
{
yield return _Selector(item);
}
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
此方法有很多优点,例如:
1)很多时候,初始化代码必须快速执行。例如,在WPF应用程序中,视图模型构造器中的代码会冻结GUI,直到完成为止。因此,最好将其保存到另一个线程中。懒惰地执行您的LINQ表达式将不会花很多时间。
2)例如,当从数据库中执行代码时,检索所有行,然后将其过滤到内存中将是非常不明智的……LINQ to SQL(与其他类LINQ to Entities相似) )使用IQueryable<T>
从表达式树构建SQL查询,然后将其发送到数据库。因此,尽管以下代码非常相似,但它们的效率却大不相同:
var x = db.ToList().Where(r => r.Id < 555);
// Versus
var x = db.Where(r => r.Id < 555).ToList();
第一个发送查询,例如SELECT * FROM [db]
,然后将结果过滤到内存中,但是第二个发送查询,例如,SELECT * FROM [db] WHERE [Id] < 555
,然后将结果转换为List<T>
。
答案 2 :(得分:1)
您完全可以摆脱null
。
根据您的样本,condition
需要“最后一个”元素,您可以将其简化为
var result = document.Elements()
.Select(versiones => versiones.Elements().Last())
.Where(last => last.condition)
.Select(last => new
{
Last = last,
Foo = bar(last)
})
.ToList();
您不必担心Where
或Select
函数的数量,集合将只被枚举一次。