2017-02-14 3 views
3

Ich bin nicht besonders kompetent mit LINQ, also könnte ich ein wenig Hilfe mit diesem bestimmten Szenario verwenden.Berechnung der Summe der Werte in einem Wörterbuch, die in einer generischen Liste vorhanden sind

Ich habe eine Liste von Wörterbuchelementen. Ich muss die Werte in dem Wörterbuch summieren, wo der Schlüssel in der Liste der Zeichenfolgen vorhanden ist.

Wie würde ich einen LINQ Ausdruck für so etwas schreiben?

Dictionary<string, decimal> cars = new Dictionary<string, decimal>(); 

cars.Add("Ford", 1.2M); 
cars.Add("Chevy", 2M); 
cars.Add("Toyota", 3M); 
cars.Add("Audi", 5M); 

List<string> selectedList = new List<string>(); 
selectedList.Add("Chevy"); 
selectedList.Add("Audi"); 
+0

Danke allen! – user7426622

Antwort

11

Genau so:

var sum = selectedList.Sum(s=>cars[s]); 

Oder wenn Sie nicht sicher sind, dass alle Werte im Wörterbuch (dank Tim Schmelter für die Korrektur) sind:

var sum = selectedList.Sum(s=>cars.ContainsKey(s)?cars[s]:0); 

EDIT: Noch besser ist die von Tim vorgeschlagene Lösung:

selectedList.Where(cars.ContainsKey).Sum(s => cars[s]) 
+0

@TimSchmelter Ich habe die Antwort aktualisiert, Sie haben recht, es war nicht sehr sicher. –

+1

Danke. Oder Sie könnten verwenden: 'selectedList.Where (cars.ContainsKey) .Summe (s => Autos [s])' –

+0

Dies wäre noch besser, wenn es 'TryGetValue' verwendet –

5

Sie könnten die Elemente aus dem Wörterbuch filtern und dann die Werte summieren:

var sum = cars 
    .Where(item => selectedList.Contains(item.Key)) 
    .Sum(item => item.Value); 
+0

Ich würde Maksim Ansatz bevorzugen. Bedenken Sie, dass das Wörterbuch Tausende von Autos enthält, aber nur 1-2 ausgewählt sind. Sie listen immer das gesamte Wörterbuch auf und profitieren nicht von dessen Nachschlageistung. –

+0

Dies wird effizienter sein als zu versuchen, ContainsKey für jeden ausgewählten Listeneintrag auszuführen –

+0

Interessanter Punkt Tim, aber was ist, wenn die Liste auch viele Einträge (und vielleicht doppelte Einträge) enthält? Das wiederholte Ausführen von 'ContainsKey', um eine weitere Suche durchzuführen, könnte eine Herausforderung werden ... Ich würde wahrscheinlich' TryGetValue' wählen und die Erweiterungen in diesem Fall nicht verwenden. –

0

Alternative nicht LINQ Antwort:

decimal total = 0; 
foreach (var car in selectedList) 
{ 
    total += cars[car]; 
} 
+0

Obwohl dies eine alternative Lösung ist, bietet LINQ eine sauberere und elegantere Lösung. –

+0

Ich stimme zu LINQ ist in der Regel eleganter wollte nur eine andere Antwort –

+0

Es ist nicht sicher, Sie erhalten eine 'KeyNotFoundException' mit einem Auto in der Liste, die nicht im Diktat ist –

1

Also hier ist ein anderer Ansatz, die ein bisschen besser für einige Kante führen könnte Fälle:

var sum = selectedList 
      .Distinct() 
      .Sum(s => 
      { 
       decimal d; 
       if (cars.TryGetValue(s, out d)) 
       { 
        return d; 
       } 
       return 0; 
      } 
     ); 

Sie wollen nur unterschiedliche Werte aus der Liste iteriert, und auf diese Weise vermeiden Sie doppelte Ting Lookups in der cars Wörterbuch (wenn das nicht der Fall ist, dann kommentieren Sie einfach die Distinct()). Dies sollte ein gutes Gleichgewicht der Leistung bieten, unabhängig davon, ob die Liste oder das Wörterbuch größer sind.

+0

Meine Erklärung aktualisiert -' .Distinct() 'kann auskommentiert werden, wenn es nicht das gewünschte Verhalten ist. –

+1

Mit C# 7 brauchen Sie nicht solche Pseudo-Linq, dann können Sie 'selectedList.Sum (c => Autos.TryGetValue (c, out Preis)? Preis: 0)', so müssen Sie nicht deklarieren out-Variablen. –

Verwandte Themen