使用LINQ创建一个IEnumerable <>的delta值

Dav*_*ave 12 c# linq statistics .net-3.5

我有一个时间戳列表(以刻度表示),从这个列表中我想创建另一个表示条目之间的增量时间的列表.

我们只是说,例如,我的主时间表如下所示:

  1. 10
  2. 20
  3. 三十
  4. 50
  5. 60
  6. 70

我想要的是这个:

  1. 10
  2. 10
  3. 20
  4. 10
  5. 10

我在这里要完成的是通过计算标准偏差来检测输出表中的#3是异常值.我以前没有统计过,但我想如果我在输出列表中查找流行值并丢弃1 sigma之外的任何内容,这对我来说就足够了.

我希望能够使用单个LINQ查询创建输出列表,但我还没有想出来.目前我只是通过循环强制它.

Ani*_*Ani 16

如果您运行的是.NET 4.0,这应该可以正常工作:

var deltas = list.Zip(list.Skip(1), (current, next) => next - current);
Run Code Online (Sandbox Code Playgroud)

除了多个调查员,这是非常有效的; 它应该适用于任何类型的序列.

这是.NET 3.5的替代方案:

var deltas = list.Skip(1)
                 .Select((next, index) => next - list[index]);
Run Code Online (Sandbox Code Playgroud)

显然,这个想法只有在使用列表的索引器时才会有效.修改它以使用ElementAt可能不是一个好主意:非IList<T>序列将发生二次运行时.在这种情况下,编写自定义迭代器是一个很好的解决方案.

编辑:如果你不喜欢Zip+的Skip(1)想法,写这样的扩展(未经测试)可能在这些情况下有用:

public class CurrentNext<T>
{
    public T Current { get; private set; }
    public T Next { get; private set; }

    public CurrentNext(T current, T next)
    {
        Current = current;
        Next = next;
    }
}

...

public static IEnumerable<CurrentNext<T>> ToCurrentNextEnumerable<T>(this IEnumerable<T> source)
{
    if (source == null)
        throw new ArgumentException("source");

    using (var source = enumerable.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            yield break;

        T current = enumerator.Current;

        while (enumerator.MoveNext())
        {
            yield return new CurrentNext<T>(current, enumerator.Current);
            current = enumerator.Current;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以将其用作:

var deltas = list.ToCurrentNextEnumerable()
                 .Select(c=> c.Next - c.Current);
Run Code Online (Sandbox Code Playgroud)

  • 老实说,在3.5中我会编写自己的扩展方法,而不是使用LINQ中的索引访问器.但是,如果你真的想要,你可以获得Zip扩展的源代码,并在3.5中使用它 - http://blogs.msdn.com/b/ericwhite/archive/2009/07/05/comparing-two-开放式XML的文档,使用最拉链扩展,method.aspx (2认同)
  • @Steven - OP在源列表中有6个元素,在输出中有5个元素.通常,连续实体之间的差异将比原始实体少一个.一栋五层楼的建筑只有四段楼梯. (2认同)
  • @Ani,@ Jeffrey:你是对的,序列必须短一些. (2认同)