2017-08-14 7 views
2

これは私が説明するのは難しいものですから、これまでのコードから始めて、後で私が達成しようとしているコードから始めます。カスタムタイプの配列の1変数の平均を計算するには

現在のコード

Option Explicit 

Public eSigTickerArr As Variant 

' Public type to save array 
Type Watchlist 
    eSigTicker As String 
    Op As Double 
    Hi As Double 
    Lo As Double 
    Cl As Double 
    Vol As Double 
    BarTime As Variant 
End Type 
Public WatchlistArr() As Watchlist ' save an array of special type "Watchlist" 

'==================================================================== 

Sub Mainr() 

ReDim WatchlistArr(0) ' init array size 
eSigTickerArr = Array("Part1", "Part2", "Part3") 

For Each eSigTickerElem In eSigTickerArr 

    ' check if first member of array is occupied 
    If WatchlistArr(0).eSigTicker <> "" Then ' not first time running this code >> increase array size by 1 
     ReDim Preserve WatchlistArr(UBound(WatchlistArr) + 1) ' increase array size by 1 
    End If 

    ' ... Some Code, working fine .... 

    ' populate array Type with data (also works) 
    With WatchlistArr(UBound(WatchlistArr)) 
     .eSigTicker = eSigTickerElem 
     .Op = LastCSVLine(2) 
     .Hi = LastCSVLine(3) 
     .Lo = LastCSVLine(4) 
     .Cl = LastCSVLine(5) 
     .Vol = LastCSVLine(6) 
     .BarTime = LastCSVLine(1) 
    End With 

Next eSigTickerElem 

' ******* calculate the average of only "Hi" ****** 
Dim myAvg 

myAvg = WorksheetFunction.Average(WatchlistArr.Hi) '<--- Getting an Error ! 

End Sub 

私は、上記の行でエラーを取得しています。

マイチャレンジ:私は私のタイプの配列WatchlistArrの特定の変数の平均値を取得したい、と10,000レコード(またはそれ以上)があることができて、私は、ループを使用する必要はありません。

Average機能で値を取得する方法はありますか。

2次元配列に切り替える必要がありますか?多分3次元配列ですか?

+0

なぜループを使いたくないのですか?数千回の繰り返しでも非常に高速です。 – Graham

+1

「平均」はどのように実装されていますか?ああ、そうだよ!ループ! –

答えて

1
myAvg = WorksheetFunction.Average(WatchlistArr.Hi) '<--- Getting an Error ! 

イエップ。何このコードがするを意味することは次のようになります。item => item.HiwatchListArr内のすべての項目ためを呼び出されるセレクタ機能である

myAvg = watchListArr.Select(item => item.Hi).Average(); 

。唯一の問題は、これがVBAではなくLINQ/C#であることです。 VBAはデリゲートやその他のファンキーなものをサポートしていません。

しかし、VBA あなたは、アレイ内のすべてのアイテムのアクションを実行してみましょう制御フロー構造を持っている:Forループを使用!あなたがApplication.WorksheetFunction.Averageを使用したい場合は

Dim i As Long, total As Double, count As Long 
For i = LBound(watchListArr) To UBound(watchListArr) 
    total = total + watchListArr(i).Hi 
    If watchListArr(i).Hi <> 0 Then count = count + 1 'assuming zeroes are excluded 
Next i 
If count <> 0 Then myAvg = total/count 

、あなたは独自の配列にあなたの配列内のすべてのアイテムのHiメンバーをコピーする必要があり、それがこと配列あげる - それが必要になります...ループ...ループが無ければ無駄になります。平均値を計算します。

For Eachループを使用して配列を繰り返し処理しない限り、うまくいくはずです。 Forループで30Kアイテムの配列を反復することは、ほとんど瞬時に行われ、心配はありません。

+0

ありがとう、〜30,000レコードまでループするのにどれくらい時間がかかりますか? 2D配列に切り替えるかどうか議論していますか?私はループをエスケープするために3D配列に行く必要があるかもしれません。私の質問はそれの価値があるのですか? –

+0

@ShaiRadoよく30Kの項目を設定するための1回の反復と30Kの項目のそれぞれのUDTの1つの要素の合計を計算するもう1回の簡単なテストを書いたところ、2つのループは即座に完了しました。パフォーマンスが実際の問題になるまで私はパフォーマンスについて心配しません。 「時期尚早最適化」という言葉を聞いたことがありますか? BTW 'WorksheetFunction.Average'はループを排除するものではありません。**あなたの*コードから抽象化するだけです。 –

+0

あなたはまだ番号1です! –

1

あなたは2次元配列としてWatchlistArrを定義し、このロジックを試みることができる:

myAvg = WorksheetFunction.Average(myArray) 

Dim myArray As Variant 
myArray = Application.WorksheetFunction.Index(WatchlistArr, 0, 2) 

これは、平均メソッドに渡すことができ、配列、などとして、列2を返します。

関連する問題