2017-07-04 15 views
-1

次のLINQの例では、グループが構成されている元の行からどのようにインデックス番号のリストを取得できますか?私はデータがどこから来るのかをユーザーに見せたいと思います。結果についてLINQクエリ結果のソース行を取得しますか?

Dim inputDt As New DataTable 
    inputDt.Columns.Add("Contractor") 
    inputDt.Columns.Add("Job_Type") 
    inputDt.Columns.Add("Cost") 

    inputDt.Rows.Add({"John Smith", "Roofing", "2408.68"}) 
    inputDt.Rows.Add({"John Smith", "Electrical", "1123.08"}) 
    inputDt.Rows.Add({"John Smith", "Framing", "900.99"}) 
    inputDt.Rows.Add({"John Smith", "Electrical", "892.00"}) 

    Dim results = From rows In inputDt Where rows!Contractor <> "" 
        Group rows By rows!Job_Type 
        Into cost_total = Sum(CDec(rows!Cost)) 

    For Each r In results 
     ' Show results. 
     'r.Job_Type 
     'r.cost_total 

     ' Show line numbers of original rows... ? 
    Next 

(JOB_TYPE =、 "電気" cost_total = 2015.08)、元のインデックス番号は1と3

おかげ

+0

は、あなたが気に情報を格納するために匿名型を作成します。インディーズ(CSV、コレクション)の保存方法に応じて、その情報を保存します。 'rows!Cost'それよりむしろ' row.Field(Decimal)( "cost") 'を使い、古いスタイルのVB6関数/表記を取り除くことができます – Plutonix

+0

@Plutonixわかりません。だから、どのように結果のアイテムのそれぞれの根底にある行に到達するのですか?例が分かるだろう。 – stacker

答えて

1

まず、おそらく最も重要な、Option Strict Onに設定されています。これは古いVB6スタイルrows!Cost型表記を許可しません。しかし、これはより良い方法です。その方法は常にObjectを返し、データはまれです。これは、NETが変数を入力し変換するより良い方法を持っているので、全く損失がありません。

第2に、やや関連性がありますが、あなたのDataTableの列はすべて、明らかに10進数であってもテキストです。次に、テーブルのデータを使用してクエリを実行することに関連しますが、DataRowプロパティも少し奇妙です。識別子として機能するようにデータにIdまたはNumberを追加する方が良いでしょう。これは、ビュー(行の順序)が変更された場合にも、結果が意味をなされるのに役立ちます。

インデックス(現在のID)またはそれらのコレクションのCSVを使用するかどうかを明確にしていません。それらのCSVはよりシンプルに見えるので、これは何をしているのですか。

このコードでは、より多くの慣用名が使用され、他の拡張メソッドを使用して必要な型にデータをキャストする方法も示しています。また、拡張メソッドの手法も使用します。まず、指定された文字列以外のデータ型とのDataTable:

Dim inputDt As New DataTable 
inputDt.Columns.Add("ID", GetType(Int32)) 
inputDt.Columns.Add("Contractor") 
inputDt.Columns.Add("JobType") 
inputDt.Columns.Add("Cost", GetType(Decimal)) 

inputDt.Rows.Add({1, "John Smith", "Roofing", "2408.68"}) 
inputDt.Rows.Add({5, "John Smith", "Electrical", "1123.08"}) 
inputDt.Rows.Add({9, "John Smith", "Framing", "900.99"}) 
inputDt.Rows.Add({17, "John Smith", "Electrical", "892.00"}) 

は、クエリ:

Dim summary = inputDt.AsEnumerable().GroupBy(Function(g) g.Field(Of String)("JobType"), 
              Function(k, v) New With {.Job = k, 
                    .Cost = v.Sum(Function(q) q.Field(Of Decimal)("Cost")), 
                    .Indices = String.Join(",", inputDt.AsEnumerable(). 
                            Where(Function(q) q.Field(Of String)("JobType") = k). 
                            Select(Function(j) j.Field(Of Int32)("Id"))) 
                    }). 
           OrderBy(Function(j) j.Cost). 
           ToArray() 

' Debug, test: 
For Each item In summary 
    Console.WriteLine("Job: {0}, Cost: {1}, Ids: {2}", item.Job, item.Cost, item.Indices) 
Next 

過度のスクロールが残念ですが、私は句は何を「レベル」に合わせてできるように、それを左に彼らは〜で働いている。ご覧のように、DataTableで個別のクエリが実行され、一致するIndiciesが取得されます。

それはもう少し一般的な

Dim foo = Something.GroupBy(...).Select(...) 

のようなものを書くことです。しかし、あなたは上記の場合と同様にthis overload of GroupByを使用してSELECTをスキップすることができます

Dim foo = Something.GroupBy(Function (g) ..., Function (k, v) ...) 

結果:

仕事:フレーミング、費用:900.99、ID:9
仕事:電気、コスト: 2015.08、のIds:5,17
仕事:屋根、費用:2408.68、Idsは:1

関連する問題