0

生の計算データの時間スケールを約2分から5分(およびそれ以降の他のより大きなスケール)の時間密度で増やす関数を書いています。時系列ではない配列に保持されている10万を超えるデータポイントがあります。配列をクエリし、2つの日時内にデータを見つけるための最速の方法を探しています。コードが実行されると、すべてのデータポイントを1回だけ使用する必要がありますが、データが正常でないため、数回読み取る必要があります。私はこれを行う方法についていくつかのアイデアを持っています:

配列内のすべての時刻値を調べて、指定された2つの日時内にあるかどうかを確認してください。これにより、新しい時点ごとに最大50k回、コードが配列全体を実行するようになります。

値が使用された場合にtrueになるtimedataを使用して配列にブール値を作成します。これは、日時比較の前に使用されたポイントのブールチェックを使用します。これはより高速であるはずです。

配列を順番に再編成します。日時に基づいて、これにかかる時間はわかりません。そもそもデータのインポートに必要な時間が大幅に増加しますが、スケーリングクエリがはるかに高速になる可能性があります。配列を順不同で実行する場合と比較して、配列を並べ替えるのにかかる時間の比率について漠然と考えていますか?

他の提案は大歓迎です。

必要だと思われる場合は、コードを追加します。前もって感謝します。

編集:要求に応じていくつかの例。

アレイの定義は次のとおりです。

    Dim ScaleDate(0) As Date
    Dim ScaleData(0) As Double

redim preserveSQLでデータを追加するので使っています。

配列からコピーされた日時ポイントの例を次に示します。

(0) = #2/12/2012 12:01:36 AM#
4

1 に答える 1

2

まず、Tim Schmelterが推奨したList(Of T)ように、配列の代わりに使用します。それはおそらくより効率的であり、間違いなく扱いやすいでしょう。次に、アイテムの各プロパティを個別のリストに保存するのではなく、単一のアイテムのすべてのデータを保存する独自のタイプを定義することをお勧めします。そうすることで、将来の変更が容易になりますが、リストのサイズを2つではなく1つだけ変更する必要があるため、より効率的になります。

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()

リストは、変更されるたびに1回だけソートする必要があります。リストを検索するたびに並べ替える必要はありません。また、それ自体を並べ替えても、前後の検索が速くなるわけではないため、並べ替えられたリストをすばやく検索するfindメソッドを実装する必要があります。たとえば、これらの線に沿った何かが機能するはずです:

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))オブジェクトを使用してアイテムのリストを保存する価値があります。これには、日付ごとに個別のアイテムのリストが含まれ、すべてハッシュテーブルに格納されます。したがって、特定の日のアイテムのリストを取得または設定するのは非常に高速ですが、日付範囲内のすべてのアイテムのリストを取得するには、日付範囲内の毎日をループしてリストを取得する必要がありますその日の辞書から、それらを1つの一致リストに結合します。

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
于 2012-09-19T12:13:37.337 に答える