我希望能够做的是构建一个LINQ查询,当其中一个字段发生变化时,它会从某些DataRows中检索一些值.这是一个人为的例子来说明:
Observation Temp Time ------------- ---- ------ Cloudy 15.0 3:00PM Cloudy 16.5 4:00PM Sunny 19.0 3:30PM Sunny 19.5 3:15PM Sunny 18.5 3:30PM Partly Cloudy 16.5 3:20PM Partly Cloudy 16.0 3:25PM Cloudy 16.0 4:00PM Sunny 17.5 3:45PM
当观察从前一个观察发生变化时,我只想检索条目.所以结果将包括:
Cloudy 15.0 3:00PM Sunny 19.0 3:30PM Partly Cloudy 16.5 3:20PM Cloudy 16.0 4:00PM Sunny 17.5 3:45PM
目前有代码迭代DataRows并进行结果的比较和构建,但希望使用LINQ来实现这一目标.
我想做的是这样的事情:
var weatherStuff = from row in ds.Tables[0].AsEnumerable() where row.Field("Observation") != weatherStuff.ElementAt(weatherStuff.Count() - 1) ) select row;
但这不起作用 - 并且不会编译,因为它在声明之前尝试使用变量'weatherStuff'.
可以用LINQ做我想做的事吗?我在SO上没有看到像这样的另一个问题,但可能错过了它.
这是一个更普遍的想法,可能是相互影响.它比@tvanfosson发布的更复杂,但在某种程度上,我觉得它更优雅:-).您要执行的操作是使用第一个字段对观察结果进行分组,但是每次值更改时您都希望启动一个新组.然后,您要选择每个组的第一个元素.
这听起来几乎像LINQ,group by
但它有点不同,所以你不能真正使用标准group by
.但是,您可以编写自己的版本(这是LINQ的奇迹!).您可以编写自己的扩展方法(例如GroupByMoving
),也可以编写将类型更改IEnumerable
为某个接口的扩展方法,然后GroupBy
为此接口定义.生成的查询将如下所示:
var weatherStuff = from row in ds.Tables[0].AsEnumerable().AsMoving() group row by row.Field("Observation") into g select g.First();
唯一剩下的就是定义AsMoving
和实施GroupBy
.这有点工作,但它通常是有用的东西,它也可以用来解决其他问题,所以它可能值得这样做:-).我的帖子的摘要是关于LINQ的好处是你可以自定义操作符的行为以获得非常优雅的代码.
我没有测试过,但实现应该如下所示:
// Interface & simple implementation so that we can change GroupBy interface IMoving: IEnumerable { } class WrappedMoving : IMoving { public IEnumerable Wrapped { get; set; } public IEnumerator GetEnumerator() { return Wrapped.GetEnumerator(); } public IEnumerator GetEnumerator() { return ((IEnumerable)Wrapped).GetEnumerator(); } } // Important bits: static class MovingExtensions { public static IMoving AsMoving (this IEnumerable e) { return new WrappedMoving { Wrapped = e }; } // This is (an ugly & imperative) implementation of the // group by as described earlier (you can probably implement it // more nicely using other LINQ methods) public static IEnumerable > GroupBy (this IEnumerable source, Func keySelector) { List elementsSoFar = new List (); IEnumerator en = source.GetEnumerator(); if (en.MoveNext()) { K lastKey = keySelector(en.Current); do { K newKey = keySelector(en.Current); if (newKey != lastKey) { yield return elementsSoFar; elementsSoFar = new List (); } elementsSoFar.Add(en.Current); } while (en.MoveNext()); yield return elementsSoFar; } }