2016-04-28 7 views
0

辞書から最大値10を取得する必要があります。私は次のようなデータを持っています:Excel VBA Max 10辞書の値

ID Value 
1 23 
2 342 
5 -23 
... 

これを行う最も速い方法は何ですか?私は実際にいくつかの値が必要になるので、私はC#のカスタムクラスの2番目の値が含まれている

class Custom { 
    int ID {get; set;} 
    double Val {get; set;} 
    double Val2 {get; set;} 
} 

List<Custom> GetMaxValues(List<Custom> myList){ 
    return myList.SortByDescending(c => c.Val).Take(10); 
} 

次のことをより明確にするためには、私はC#でこれを行うだろうかのコードリストであります辞書に多次元配列は、データの三つ組を保持する良い解決策になるでしょうか?それから私は単純にいくつかのソートアルゴリズムを実行し、配列から最後の10項目を選ぶことができました。

編集:データの種類が異なるため、配列を使用できないことに気付きました。 IDは実際には文字列であり、整数ではありません。

+3

なぜこのラベルはVBAのC#コードですか? –

+0

あなたの既存のコードは何ですか?辞書の順序は保証されていません。配列に関しては、さまざまなタイプの多変量配列を使用することができます。 – SWa

+1

@iDevlopこれは最初に私を投げましたが、C#コードはVBAで何をしたいのかを説明することです。どのように私はこのC#をVBAに翻訳するのでしょうか? –

答えて

1

を私は配列に辞書からトップN値を返す必要がありますいくつかのVBAを生成しました。私はヘルパー関数に分解して、少し読みやすくし、再利用のために職務を分けようとしました。確かに、それはエラーチェックのためにさらに開発することができますが、私はそれを比較的早く嘲笑しました(例えば重複は無視されます)。

あなたが必要とすることをしているのか、独自のコードへの採用に関する助けが必要な場合はお知らせください。

Sub PerformTheActions() 
    Dim oDictionary As Object 

    Set oDictionary = CreateObject("Scripting.Dictionary") 

    AddToDictionary oDictionary, Sheet1.Range("A1:A33") 

    va = ReturnTopNValuesFromDict(oDictionary, 10) 

    For i = LBound(va) To UBound(va) 
     MsgBox "Key: " & va(i, 1) & " Value: " & va(i, 2) 
    Next i 

End Sub 

' Below is just a helper function to add a bunch of numbers into a dictionary 
' You won't need to use it because you likely have other business logic to create your dict 
Private Sub AddToDictionary(odict As Object, rng As Range) 
    Dim cel As Range 
    Dim nID As Integer 

    nID = 1 
    For Each cel In rng 
     If Not odict.exists(cel.Value) Then 
      odict.Add nID, cel.Value 
      nID = nID + 1 
     End If 
    Next cel 

End Sub 

Private Function ReturnTopNValuesFromDict(odict As Object, nTop As Integer) As Variant() 
    Dim topN() As Variant 
    Dim nCounter As Integer 
    Dim vCutoff As Variant 
    Dim nCutoffIndex As Long 

    ReDim topN(1 To nTop, 1 To 2) 
    nCounter = 1 

    For Each oitem In odict 
     If nCounter <= nTop Then 
      topN(nCounter, 1) = oitem 
      topN(nCounter, 2) = odict(oitem) 
      nCounter = nCounter + 1 
     Else 
      vCutoff = topN(LBound(topN), 2) 
      nCutoffIndex = LBound(topN) 

      For i = LBound(topN) + 1 To UBound(topN) 
       If topN(i, 2) < vCutoff Then 
        vCutoff = topN(i, 2) 
        nCutoffIndex = i 
       End If 
      Next i 

      If vCutoff > odict(oitem) Then 
       'Do nothing because lowest value in array is greater than this item 
      Else 
       topN(nCutoffIndex, 1) = oitem 
       topN(nCutoffIndex, 2) = odict(oitem) 
      End If 
     End If 
    Next oitem 
    BubbleSortArray topN 
    ReturnTopNValuesFromDict = topN 
End Function 

Private Function BubbleSortArray(vArray As Variant) As Variant() 
    Dim vPlaceHolder As Variant 
    Dim nFirst As Long 
    Dim nSecond As Long 


    For nFirst = LBound(vArray) To UBound(vArray) 
     For nSecond = nFirst + 1 To UBound(vArray) 
      If vArray(nFirst, 2) < vArray(nSecond, 2) Then 
       vPlaceHolder = vArray(nFirst, 1) 
       vArray(nFirst, 1) = vArray(nSecond, 1) 
       vArray(nSecond, 1) = vPlaceHolder 

       vPlaceHolder = vArray(nFirst, 2) 
       vArray(nFirst, 2) = vArray(nSecond, 2) 
       vArray(nSecond, 2) = vPlaceHolder 
      End If 
     Next nSecond 
    Next nFirst 
End Function 
2

は、辞書を使用しないでください - 代わりのArrayListを使用します。

Sub foo() 

Dim myList As Object 
Dim resultArray As Variant 

'// create the arraylist and populate it 
Set myList = CreateObject("System.Collections.ArrayList") 

For i = 100 To 1 Step -1 
    myList.Add i 
Next 

'// sort the values numerically 
myList.Sort 

'// remove the last 90 elements (we're only interested in the first 10) 
myList.RemoveRange 10, myList.Count - 10 

'// pass the values to a single dimension array 
resultArray = myList.ToArray() 

'// print the results 
Debug.Print Join$(resultArray, ",") 

End Sub 

MSDN ArrayList Class

+0

私はそれが好きです。辞書が必要ない場合の別の良いアイデア。 – user3561813