我有大量从数据库中检索的数据。它们按时间戳排序(每个项目都有),我希望能够快速滚动浏览这些数据,并能够在特定时间内检索下一个/上一个记录。
是否有任何数据结构可以帮助我这样做?目前,我通过数据进行二元搜索以检索下一个项目。
插入,删除和编辑很少见(但偶尔也有必要),因此寻找时间是最关键的。
有什么想法吗?
一个简单的例子:
public class TimedDataItem
{
DateTime Timestamp { get; set; }
}
// Large populated timestamped data set
IList<TimedDataItem> timedDataItemsList = new Last<TimedDataItem>();
// Get a 'random' time
DateTime myTime = DateTime.Now;
// Find items around that 'random' time
TimedDataItem next = timedDataItemsList.FirstOrDefault(t=>t.Timestamp > myTime);
TimedDataItem previous = timedDataItemsList.LastOrDefault(t=>t.Timestamp < myTime);
// Also foreach over the collection in time order if required
foreach (TimedDataItem item in timedDataItemsList)
DoStuff(item);
// Inserts, deletions, edits are extremely rare
感谢。
答案 0 :(得分:3)
编辑回答
首选解决方案 - SortedSet
plus:排序集合,允许逻辑使用某个范围内的元素
减:不确定搜索算法是什么,没有上一个和下一个
public class TimedDataItem
{
public DateTime Timestamp { get; set; }
}
class TimedDataItemComparer : IComparer<TimedDataItem>
{
public int Compare(TimedDataItem x, TimedDataItem y)
{
return x.Timestamp.CompareTo(y.Timestamp);
}
}
class Program
{
static void Main(string[] args)
{
SortedSet<TimedDataItem> ss =
new SortedSet<TimedDataItem>(new TimedDataItemComparer());
// example data
ss.Add(new TimedDataItem() { Timestamp = DateTime.Now.AddDays(-5) });
TimedDataItem min = new TimedDataItem() { Timestamp = DateTime.Now.AddDays(-3) };
ss.Add(min);
ss.Add(new TimedDataItem() { Timestamp = DateTime.Now.AddDays(-1) });
ss.Add(new TimedDataItem() { Timestamp = DateTime.Now });
ss.Add(new TimedDataItem() { Timestamp = DateTime.Now.AddDays(1) });
TimedDataItem max = new TimedDataItem() { Timestamp = DateTime.Now.AddDays(3) };
ss.Add(max);
ss.Add(new TimedDataItem() { Timestamp = DateTime.Now.AddDays(5) });
// get elements in range
SortedSet<TimedDataItem> view = ss.GetViewBetween(min, max);
foreach (TimedDataItem item in view)
{
Console.WriteLine(item.Timestamp);
}
}
}
解决方案SortedList
plus: sorted,typeSafe,允许next和prev
减:线性搜索
SortedList<TimedDataItem, TimedDataItem> sl =
new SortedList<TimedDataItem, TimedDataItem>(new TimedDataItemComparer());
TimedDataItem first = new TimedDataItem() { Timestamp = DateTime.Now.AddDays(-5) };
TimedDataItem second = new TimedDataItem() { Timestamp = DateTime.Now.AddDays(-3) };
TimedDataItem third = new TimedDataItem() { Timestamp = DateTime.Now.AddDays(-1) };
TimedDataItem fourth = new TimedDataItem() { Timestamp = DateTime.Now };
TimedDataItem fifth = new TimedDataItem() { Timestamp = DateTime.Now.AddDays(1) };
TimedDataItem sixth = new TimedDataItem() { Timestamp = DateTime.Now.AddDays(3) };
TimedDataItem seventh = new TimedDataItem() { Timestamp = DateTime.Now.AddDays(5) };
sl.Add(first, first);
sl.Add(second, second);
sl.Add(third, third);
sl.Add(fourth, fourth);
sl.Add(fifth, fifth);
sl.Add(sixth, sixth);
sl.Add(seventh, seventh);
// unfortunatelly according to MSDN:
// This method uses a linear search; therefore, this method is
// an O(n) operation, where n is Count.
int index = sl.IndexOfKey(third);
TimedDataItem prev = sl.ElementAt(index - 1).Value;
TimedDataItem next = sl.ElementAt(index + 1).Value;
解决方案ArrayList
plus:允许使用索引binarySearch(!)
减:你应该怎样处理无序集合中的索引......
ArrayList al = new ArrayList();
al.Add(first);
al.Add(second);
al.Add(third);
al.Add(fourth);
al.Add(fifth);
al.Add(seventh);
al.Add(seventh);
int index2 = al.BinarySearch(third, new TimedDataItemComparer2());
// al[index2] does not make sense
// as there is no guarantee, that al[index2-1] is the element
// with previous DateTime ...
class TimedDataItemComparer2 : IComparer
{
public int Compare(object x, object y)
{
if (x is TimedDataItem && y is TimedDataItem)
return ((TimedDataItem)x).Timestamp.
CompareTo(((TimedDataItem)y).Timestamp);
else
return -1;
}
}