2016-08-03 8 views
1

フィルタリングしてタプルをキーとして辞書を合計しようとしています。 SOにはlinksの2つがありますが、それほど広範囲なものはありません。何か提案してください。フィルターをタプルをキーとして合計

Dictionary<Tuple<int, string, string, int, string>, double> dctMC = new Dictionary<Tuple<int, string, string, int, string>, double>(); 
List<int> listIDs = new List<int> { 1, 3, 5 }; 

// ID, TYPE, NAME, ORDER, COLOUR, WEIGHT 
dctMC.Add(Tuple.Create(1, "Fruit", "Apple", 9, "Green"), 0.45); 
dctMC.Add(Tuple.Create(2, "Fruit", "Grape", 5, "Red"), 0.78); 
dctMC.Add(Tuple.Create(3, "Fruit", "Apple", 9, "Green"), 0.33); 
dctMC.Add(Tuple.Create(4, "Fruit", "Peach", 2, "Yellow"), 0.89); 
dctMC.Add(Tuple.Create(5, "Fruit", "Apple", 14, "Red"), 0.23); 

// Sum dictionary where IDs in listIDs, Type = FRUIT, Name = APPLE, Order = 9, Colour = "Green" 
double TOTAL = dctMC.Where(Z => listIDs.Contains(Z.Key(item1)) && 
           Z.Key(item2) == "Apple" && 
           Z.Key(item3) == 9 && 
           Z.Key(item4) == "Green") 
        .Sum() 
+0

問題を理解して解決するのをもっと簡単にする:) –

答えて

4

タプルのキー内の項目にアクセスする間違いがあります。彼らは彼の財産です。

あなたは言葉にそれを置くしようとするのであれば、それは一種のです:終わり"Item in dictionary(KeyValuePair<>).Key.(Key is a tuple with 5 fields - so select property of that field)"

- あなたの要求に合うアイテムを見つけた後、あなたはIEnumerable<KeyValuePair<>>を取り戻すので、あなたがSumあなたがで指定する必要があります何の - この場合はValueのペアです。

double TOTAL = dctMC.Where(Z => listIDs.Contains(Z.Key.Item1) && 
           Z.Key.Item2 == "Apple" && 
           Z.Key.Item4 == 9 && 
           Z.Key.Item5 == "Green") 
        .Sum(item => item.Value); 

は**あなたが誤ってこれが問題のためであるかないものの場合は分からない代わりにItem5 *


Item3 == 9代わりにItem4 == "Green"Item4と同じを使用していることも注意してください私はそのようなTuplesから離れることを提案し、適切な定義されたクラス(または他のクエリの場合は匿名タイプ)に入れてください。

+0

助けてくれてありがとう - 私は大規模なシミュレーションを実行しています。追加する前に分析して結果を辞書に保存しようとしていますキー/値のペアにアクセスするためにループを使用してデータテーブルに戻ります。これを行うより良い方法があれば、正しい方向に私を向けることができますか?私はネストされた辞書の代わりにタプルを使うことにしました。 – Zeus

+0

これは階層化されたデータを処理するより良い方法ですか? (http://stackoverflow.com/questions/24708236/c-sharp-nested-dictionary-better-alternative-best-organize-data-across-three-c) – Zeus

+0

@Zeus - 詳細は見ていませんでしたがタプルをクラスで5つのフィールドに置き換えている場合 - 答えはyesです。 –

2

辞書を繰り返し処理するときは、要素はKeyValuePair<>インスタンスです。あなたはそれらを合計した値をSelectする必要があります。

double TOTAL = dctMC.Where(Z => 
         lstIDs.Contains(Z.Key.Item1)) && 
         Z.Key.Item2 == "Apple" && 
         Z.Key.Item4 == 9 && Z.Key.Item5 == "Green") 
        .Select(Z => Z.Value) 
        .Sum(); 

または、このようなセレクタラムダとSum()オーバーロードを使用します。Tuple<>内のアイテムがtuple.Item1tuple.Item2などのようにアクセスされていることを

double TOTAL = dctMC.Where(Z => 
         lstIDs.Contains(Z.Key.Item1)) && 
         Z.Key.Item2 == "Apple" && 
         Z.Key.Item4 == 9 && Z.Key.Item5 == "Green") 
        .Sum(Z => Z.Value); 

注意、ないtuple(item1)

+0

これはコンパイルされません - 'Item3'が文字列であると... –

+0

@GiladGreen THX、何とかインデックスを混同している必要がありますされて - それは彼のオリジナルコードのエラーでした: ) –

+0

なく、あなたの間違いを編集中' Item4'がint –

2

あなたがステージにそれを破る場合には、その周りにあなたの頭をラップする方が簡単です:非該当する項目(キーによる)アウト
まずフィルタ、その後、値を合計:

初期化を追加するための良い
var filtered = //This is an IEnumerable of KeyValuePair<Tuple<int, string, string, int, string>, double> 
    dctMC.Where(Z => listIDs.Contains(Z.Key.Item1) && 
             Z.Key.Item2 == "Apple" && 
             Z.Key.Item4 == 9 && 
             Z.Key.Item5 == "Green") 
var values = filtered.Select(item => item.Value); //the doubles you want to sum 
double TOTAL = values.Sum();       //The sum you were looking for... 
+0

すべての助けてくれてありがとう!!私はコードを手に入れましたが、Gilad Greenのように、上記のコメントがおそらく良い方法でしょう。 – Zeus

関連する問題