我正在编写一个函数来增加原始计算数据的时间尺度,时间密度约为2分钟到5分钟(之后的其他更大的尺度)。数组中保存的数据点超过100k,不按时间顺序排列。我正在寻找查询数组和在两个日期时间内查找数据的最快方法。由于代码运行,每个数据点只需要使用一次,但由于数据不按顺序,因此必须多次读取。我有几个关于如何做到这一点的想法:
只需查看数组中的所有时间值,检查它们是否在给定的两个日期时间内。这将强制代码在每个新时间点运行整个数组~50k次。
使用我的timedata在数组中创建一个布尔值,如果已使用该值,该数据将变为true。这将使用在日期时间比较之前使用的点的布尔检查,该检查应该更快。
将数组重组为顺序,我不确定根据日期时间需要多长时间。它会大大增加首先导入数据所需的时间,但是它可以使缩放查询更快。是否有任何想法模糊地重新排序数组所需的时间与无序运行相比?
欢迎任何其他建议。
如果有人觉得有必要,我会添加一些代码。提前谢谢。
编辑:请求的几个例子。
以下是数组的定义:
Dim ScaleDate(0) As Date
Dim ScaleData(0) As Double
我使用redim preserve
,因为数据通过SQL添加到它们中。
以下是从数组中复制的日期时间点的示例。
(0) = #2/12/2012 12:01:36 AM#
答案 0 :(得分:2)
首先,正如Tim Schmelter建议的那样,我会使用List(Of T)
而不是数组。它可能会更高效,并且肯定会更容易使用。其次,我建议您定义自己的类型,它存储单个项目的所有数据,而不是将项目的每个属性存储在单独的列表中。这样做会使将来更容易修改,但它也会更有效率,因为你只需要调整一个列表而不是两个:
Public Class MyItem
Public Property ScaleDate() As Date
Get
Return _scaleDate
End Get
Set(ByVal value As Date)
_scaleDate = value
End Set
End Property
Private _scaleDate As Date
Public Property ScaleData() As Double
Get
Return _scaleData
End Get
Set(ByVal value As Double)
_scaleData = value
End Set
End Property
Private _scaleData As Double
End Class
Private _myItems As New List(Of MyItem)()
很难说哪个更快,排序列表或搜索列表。这一切都取决于它的大小,它的变化频率以及搜索频率。因此,我建议您尝试使用这两个选项并亲自查看哪些选项在您的方案中更有效。
对于排序,如果您有自己的类型,则只需将其设为IComparable(Of T)
,然后调用列表中的Sort
方法:
Public Class MyItem
Implements IComparable(Of MyItem)
Public Property ScaleDate() As Date
Get
Return _scaleDate
End Get
Set(ByVal value As Date)
_scaleDate = value
End Set
End Property
Private _scaleDate As Date
Public Property ScaleData() As Double
Get
Return _scaleData
End Get
Set(ByVal value As Double)
_scaleData = value
End Set
End Property
Private _scaleData As Double
Public Function CompareTo(ByVal other As MyItem) As Integer Implements IComparable(Of MyItem).CompareTo
Return ScaleDate.CompareTo(other.ScaleDate)
End Function
End Class
Private _myItems As New List(Of MyItem)()
'To sort the list after it's been modified:
_myItems.Sort()
每次修改时,您只希望对列表进行排序。每次搜索列表时都不希望对其进行排序。此外,对其进行排序和单独进行排序并不能更快地进行前后搜索,因此您需要实现一种快速搜索排序列表的查找方法。例如,沿着这些方向的东西应该有效:
Private Function FindIndex(ByVal startDate As Date) As Integer
FindIndex(startDate, 0, _myItems.Count - 1)
End Function
Private Function FindIndex(ByVal startDate As Date, ByVal startIndex As Integer, ByVal endIndex As Integer) As Integer
If endIndex >= startIndex Then
Dim midIndex As Integer = ((endIndex - startIndex) \ 2) + startIndex
If _myItems(midIndex).ScaleDate < startDate Then
Return FindIndex(startDate, midIndex, endIndex)
Else
Return FindIndex(startDate, startIndex, midIndex)
End If
Else
Return startIndex
End If
End Function
为了搜索未排序的列表,我只需在整个列表中前后循环,然后创建所有匹配项的新列表:
Dim matches As New List(Of MyItem)()
For Each item As MyItem In _myItems
If (item.ScaleDate >= startDate) And (item.ScaleDate <= endDate) Then
matches.Add(item)
End If
Next
或者,如果这些项目上的日期大部分是连续的,而它们之间没有巨大的间隙,那么使用Dictionary(Of Date, List(Of MyItem))
对象来存储项目列表可能是值得的。这将包含每个日期的单独项目列表,所有项目都存储在哈希表中。因此,获取或设置特定日期的项目列表会非常快,但要获取日期范围内所有项目的列表,您必须遍历日期范围内的每一天并获取列表那天从字典中将它们组合成一个匹配列表:
Dim _days As New Dictionary(Of Date, List(Of MyItem))()
'You'd need to loop through and add each item with code like this:
Private Sub AddItem(ByVal item As MyItem)
Dim dayItems As List(Of MyItem) = Nothing
_days.TryGetValue(item.ScaleDate, dayItems)
If dayItems Is Nothing Then
dayItems = New List(Of MyItem)()
_days(item.ScaleDate) = dayItems
End If
dayItems.Add(item)
End Sub
'And then to find all the items in a date range, you could do something like this:
Private Function FindItemsInRange(ByVal startDate As Date, ByVal endDate As Date) As List(Of MyItem)
Dim matches As New List(Of MyItem)()
Dim i As Date = startDate
While i <= endDate
Dim dayItems As List(Of MyItem) = Nothing
_days.TryGetValue(i, dayItems)
If dayItems Is Nothing Then
matches.AddRange(dayItems)
End If
i = i.AddDays(1)
End While
Return matches
End Function