12 Stimmen

Wie summiere ich Werte aus zwei Wörterbüchern in C#?

Ich habe zwei Wörterbücher mit der gleichen Struktur:

Dictionary<string, int> foo = new Dictionary<string, int>() 
{
    {"Table", 5 },
    {"Chair", 3 },
    {"Couch", 1 }
};

Dictionary<string, int> bar = new Dictionary<string, int>() 
{
    {"Table", 4 },
    {"Chair", 7 },
    {"Couch", 8 }
};

Ich möchte die Werte der Wörterbücher zusammenzählen und ein drittes Wörterbuch mit den Schlüsseln und den Gesamtwerten für jeden Schlüssel zurückgeben:

Table, 9
Chair, 10
Couch, 9

Meine derzeitige Lösung besteht darin, das Wörterbuch in einer Schleife zu durchlaufen und sie auf diese Weise herauszuziehen, aber ich weiß, dass diese Lösung weder besonders leistungsfähig noch besonders lesbar ist. Allerdings stoße ich auf eine Ziegelmauer, die versucht, mit einer Lösung in LINQ zu kommen.

15voto

Tomas Petricek Punkte 233658

Die folgende Lösung ist nicht die effizienteste (weil sie einfach beide Wörterbücher als Aufzählungszeichen behandelt), aber sie wird funktionieren und ist ziemlich klar:

Dictionary<string, int> result = (from e in foo.Concat(bar)
              group e by e.Key into g
              select new { Name = g.Key, Count = g.Sum(kvp => kvp.Value) })
              .ToDictionary(item => item.Name, item => item.Count);

5voto

Carlos Punkte 5763

Wenn Sie ein Gusseisen haben, stellen Sie sicher, dass die beiden Sätze von Schlüsseln gleich sind:

Dictionary<string, int> Res2 = foo.ToDictionary(orig => orig.Key, orig => orig.Value + bar[orig.Key]);

Das Beste, was mir einfiel, wenn die Schlüssel nicht identisch sind:

var AllKeys = foo.Keys.Union(bar.Keys);
var res3 = AllKeys.ToDictionary(key => key,  key => (foo.Keys.Contains(key)?foo[key] : 0) + (bar.Keys.Contains(key)?bar[key] : 0));

4voto

Stephan Punkte 5340
(from a in foo
join b in bar on a.Key equals b.Key
select new { Key = a.Key, Value = a.Value + b.Value })
.ToDictionary(a => a.Key,a => a.Value) 

Das sollte genügen.

EDIT: Könnte effizienter sein (bin nicht sicher, wie die Verbindung implementiert ist)

(from a in foo
let b = bar.ContainsKey(a.Key) ? (int?)bar[a.Key] : null
select new { Key = a.Key, Value = a.Value + (b != null ? b : 0) }
).ToDictionary(a => a.Key, a => a.Value)

4voto

Francisco Noriega Punkte 12455

Hmm, ich weiß nicht, was mehr pro Formanten ist, aber warum ist Ihre Lösung nicht lesbar?

Was ist falsch an

  foreach (string key in d1.Keys)
  {
     d3.Add(key,d1[key]+d2[key]);
  }

?

Ich denke sogar, dass es klarer ist als einige der Linq-Lösungen. Obwohl ich es nicht getestet habe, denke ich, dass es eine bessere Leistung haben könnte, da es nur die Schlüssel in einem Wörterbuch und nicht die Werte aufzählt, würden Sie das tatsächliche Hashing (oder was auch immer die zugrunde liegende Implementierung des Wörterbuchs ist) verwenden, um die Werte zu finden, die der schnellste Weg, um sie zu erhalten ist.

EDIT:

Für die Lösung, bei der die Schlüssel nicht immer gleich sind, müssen Sie nur eine Zeile hinzufügen, wenn Sie nur gemeinsame Schlüssel erhalten möchten;

foreach (string key in d1.Keys)
  {
     if(d2.ContainsKey(key)
        d3.Add(key,d1[key]+d2[key]);
  }

EDIT2:

Um alle Schlüssel/Werte zu erhalten, wenn sie nicht gleich sind, würde es wie folgt aussehen:

   foreach (string key in d1.Keys)
      {
         if(d2.ContainsKey(key)
            d3.Add(key,d1[key]+d2[key]);
         else
            d3.Add(key,d1[key])
      }

   foreach (string key in d2.keys)
       {
          if(!d1.ContainsKey(key) // only get keys that are unique to d2
             d3.Add(key,d2[key]);
       }

2voto

Dan Tao Punkte 121990

Wie wäre es mit etwas wie diesem?

var fooBar = foo.Keys
    .Union(bar.Keys)
    .Select(
        key => {
            int fval = 0, bval = 0;

            foo.TryGetValue(key, out fval);
            bar.TryGetValue(key, out bval);

            return new KeyValuePair<string, int>(key, fval + bval);
        }
    )
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

Zumindest ist es (irgendwie?) hübsch.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X