2016-11-20 2 views
1

Gibt es eine effizientere Möglichkeit, mehrere Wörterbücher zu einem zusammenzufassen, und wenn es einen doppelten Schlüssel gibt, dann addieren Sie die Werte zusammen? Die Wörterbücher haben mindestens 10000 Schlüssel-Wert-Paare.Mehrere Wörterbücher zusammenfassen, zusammen Werte hinzufügen

Dictionary<string, int>[] res; 
Dictionary<string, int> aggregatedRes = res[0]; 
for (int i = 1; i < res.Length; i++) 
{ 
    foreach (KeyValuePair<string, int> valuePair in res[i]) 
    { 
     if (aggregatedRes.ContainsKey(valuePair.Key)) 
     { 
      aggregatedRes[valuePair.Key] += valuePair.Value; 
     } 
     else 
     { 
      aggregatedRes.Add(valuePair.Key, valuePair.Value); 
     } 
    } 
} 

fand ich viel Post auf Stackoverflow mit ähnlicher Frage, aber es, wenn es ein doppelter Schlüssel, sie fallen nur einen Wert davon, die nicht gut für mich ist.

Dictionary 1 
apple - 2 
an - 1 
I - 1 
like - 3 

Dictionary 2 
apple - 3 
car - 1 
green - 1 

Dictionary 3 
apple - 1 
green - 1 
like - 1 

Expected result: 
apple - 6 
an - 1 
I - 1 
like - 4 
car - 1 
green - 2 
+1

'Ich fand eine Menge von Post auf Stackoverflow mit ähnlicher Frage, aber dort, wenn es einen doppelten Schlüssel gab, fallen sie nur einen Wert von es ". Also, können Sie sie nicht ändern, um zusammenzufassen .... –

+0

leider nicht, wenn ich es tun kann, frage ich nicht, wie man macht – golddragon007

+2

OK Dann, wie wäre es mit der Veröffentlichung eines kompilierbaren Code und zeigt Ihr Problem .. " Ein Compilabe-Code + Sample-Eingabe + Was Sie erhalten + Erwartete Ausgabe ". –

Antwort

1

Ich sehe keine magische Weise, die viel besser ist als das, was Sie bereits tun. (Alle Tricks mit LINQ wird nicht die Leistung verbessern.) Eine leichte Verbesserung konnte der Schleife wie folgt zu ändern:

for (int i = 1; i < res.Length; i++) 
{ 
    foreach (KeyValuePair<string, int> valuePair in res[i]) 
    { 
     int value; 
     aggregatedRes.TryGetValue(valuePair.Key, out value); 
     aggregatedRes[valuePair.Key] = value + valuePair.Value; 
    } 
} 

Wenn nichts anderes, es ist ein bisschen kürzer ist.

Was wirklich helfen würde, wenn wir die Suche auf aggregatedRes nur einmal tun könnten, aber ich sehe keine Möglichkeit, das zu tun.

+0

Nun ja, es gibt keine if-Anweisung drin, das ist fast immer besser. Nun, ich bin mir in Ihrer LINQ-Aussage nicht sicher, weil einer meiner Freunde einige Benchmarks mit LINQ und mit normalen 'foreach'- und' for'-Anweisungen gemacht hat, und ich verstehe immer noch nicht, warum der LINQ war appr. 33% schneller als die anderen, wenn sie das gleiche denken ... – golddragon007

+0

@ golddragon007: Ich wäre daran interessiert, die LINQ-Formulierung zu sehen. Meinungen müssen sich natürlich den Messungen unterwerfen. :-) –

0

Haben Leistung nicht getestet, aber ein Weg Linq verwenden wäre die Wörterbücher abzuflachen (Select), Gruppe auf allen Tasten und ein neues Wörterbuch erstellen, Summieren der Gruppenwerte:

var aggregatedRes = (from d in res 
      from kv in d 
      group kv by kv.Key) 
     .ToDictionary(g=>g.Key, g=>g.Sum(kv=>kv.Value)); 

(Für die Leistung mit großen Wörterbüchern, würde das oben mit Parallelismus auch funktionieren mit from d in res.AsParallel())

Verwandte Themen