代码之家  ›  专栏  ›  技术社区  ›  Tim

按时间顺序获取最新x条目的最佳方法

  •  2
  • Tim  · 技术社区  · 14 年前

    我正在按时间顺序获取最新的x项。 目前我正在做:

    var query = db.OrderByDecending(x => x.date).Take(x).OrderBy(x => x.date)
    

    在一个方向上进行排序、限制然后在另一个方向上进行排序似乎很疯狂。它不像我现在正在使用的东西导致我失眠,我只是想知道是否有更好的方法…

    3 回复  |  直到 14 年前
        1
  •  4
  •   SLaks    14 年前

    由第二 OrderBy 调用,列表已排序,但顺序错误。因此,你可以打电话给 Reverse ,速度会更快。

    var query = db.OrderByDescending(x => x.date).Take(x).Reverse();
    
        2
  •  0
  •   Remus Rusanu    14 年前

    这取决于“db”实际上是什么。如果它是一个集合,那么slaks建议是有效的。另一方面,FF是一个SQL数据库,这是一个linq2sql查询或linq to ef,实际上这两个orderby更好。这就是SQL所要做的:描述所需的结果,让数据库引擎找出满足您请求的最佳访问路径和查询计划。

        3
  •  0
  •   ICR    14 年前

    它需要某种流缓冲区数据结构,但是您可以很容易地编写 TakeEnd 方法。尽管在这种特定的情况下,使用Reverse可能是一个更好的主意。

    这将允许您执行如下操作:

    var query = db.OrderBy(x => x.date).TakeEnd(x);
    

    使用此代码:

    public static class Ext
    {
        private class StreamBuffer<T> : IEnumerable<T>
        {
            private int head = 0;
            private bool filled = false;
    
            private T[] stream;
            public int Size { get; private set; }
    
            public StreamBuffer(int size)
            {
                Size = size;
                stream = new T[Size];
            }
    
            public void Add(T item)
            {
                stream[head] = item;
    
                head += 1;
                if (head >= Size)
                {
                    head = 0;
                    filled = true;
                }
            }
    
            public IEnumerator<T> GetEnumerator()
            {
                int start = filled ? head : 0;
                int size = filled ? Size : head;
                for (int i = 0; i < size; i += 1)
                {
                    int p = (start + i) % Size;
                    yield return stream[p];
                }
            }
    
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
    
        public static IEnumerable<T> TakeEnd<T>(this IEnumerable<T> enumerable, int count)
        {
            StreamBuffer<T> buffer = new StreamBuffer<T>(count);
            foreach (T t in enumerable)
            {
                buffer.Add(t);
            }
            return buffer;
        }
    }