2016-12-21 15 views
25

Tôi có cấu trúc này:Làm thế nào để sử dụng LINQ để tìm tổng?

private readonly Dictionary<string, Dictionary<string, int>> _storage = 
    new Dictionary<string, Dictionary<string, int>>(); 

chính: Firmware (string): Đây chính: Device (string): CountOfUsers giá trị (int)

tôi cần phải nhận được tổng số người sử dụng cho từng thiết bị, nhưng Tôi thực sự không biết làm thế nào để làm điều đó với LINQ. Đã thử rất nhiều biến thể. Hãy giúp tôi!

Còn bây giờ, tôi chỉ sử dụng một chức năng toàn bộ cho nó

private XlsRow2 GetTotalPerDevice(Dictionary<string, Dictionary<string, int>> storage) 
    { 
     XlsRow2 totalPerDeviceRow = new XlsRow2(); 
     totalPerDeviceRow._Name = "Grand Total"; 
     totalPerDeviceRow.UseBorders = true; 
     foreach (var deviceModel in _allDeviceModels) 
     { 
      foreach (var firmware in storage) 
      { 
       foreach (var device in firmware.Value) 
       { 
        var countOfUsers = 0; 
        if (deviceModel == device.Key) 
        { 
         countOfUsers += device.Value; 

         if (!_totalsPerDevice.ContainsKey(deviceModel)) 
         { 
          _totalsPerDevice.Add(deviceModel, countOfUsers); 
         } 
         else 
         { 
          _totalsPerDevice[deviceModel] += countOfUsers; 
         } 
        } 
       } 
      } 
     } 
     foreach (var deviceModel in _allDeviceModels) 
     { 
      if (_totalsPerDevice.ContainsKey(deviceModel)) 
      { 
       totalPerDeviceRow._AddColumn(_totalsPerDevice.First(k => k.Key == deviceModel.ToString()).Value.ToString()); 
      } 
      else 
      { 
       totalPerDeviceRow._AddColumn(""); 
      } 
     } 
     return totalPerDeviceRow; 
    } 

Trả lời

31

Something như thế này chẳng hạn?

var result = _storage.SelectMany(x => x.Value) 
    .GroupBy(x => x.Key) 
    .Select(x => new { Device = x.Key, Total = x.Sum(y => y.Value) }); 
11

Vì các khóa cho dữ liệu bạn muốn tổng hợp nằm trong từ điển cấp hai, bước đầu tiên là đặt tất cả các cặp khóa-giá trị từ từ điển bên trong vào một chuỗi phẳng. Sau đó bạn chỉ cần có để tổng hợp các tội, như thế này:

var res = _storage 
    .SelectMany(d => d.Value) 
    .GroupBy(kvp => kvp.Key) 
    .ToDictionary(g => g.Key, g => g.Sum(kvp => kvp.Value)); 
+0

Một lần nữa, lời khuyên không phải là allways câu trả lời hay nhất có điểm số cao nhất nhưng chỉ đơn giản là một trong số đó đã có nhiều phiếu bầu. Lấy làm tiếc. bro. – HimBromBeere

10

Một điển thực hiện IEnumerable<KeyValuePair<TKey,TValue> có nghĩa là bạn có thể sử dụng LINQ trên đó. Trong trường hợp này, bạn có một từ điển từ điển và cần nhóm theo khóa cấp thứ hai. Để làm điều đó, bạn cần phải san bằng từ điển, một cái gì đó có thể được thực hiện với SelectMany

_storage.Selectmany(pair=>pair.Value); 

Một khi bạn có các mục lá cấp, bạn có thể nhóm bằng phím của họ:

_storage.Selectmany(pair=>pair.Value) 
     .GroupBy(leaf=>leaf.Key); 

Và tính tổng cho mỗi nhóm:

var totals=_storage.SelectMany(pair=>pair.Value) 
        .GroupBy(leaf=>leaf.Key) 
        .Select(grp=>new { 
             Device = grp.Key, 
             TotalUsers =grp.Sum(leaf=>leaf.Value) 
            }); 

truy vấn tương đương là khá sạch:

var totals2 = from frm in _storage 
       from dev in frm.Value 
       group dev by dev.Key into grp 
       select new { 
          Device = grp.Key, 
          Total=grp.Sum(leaf=>leaf.Value) 
         }; 

Với từ điển sau:

var _storage = new Dictionary<string, Dictionary<string, int>> { 
    ["Frm1"]=new Dictionary<string, int> { 
        ["Device1"]=4, 
        ["Device2"]=5 
       }, 
    ["Frm2"]=new Dictionary<string, int> { 
        ["Device1"]=41, 
        ["Device3"]=5 
       }      
}; 

Cả hai truy vấn trả lại giá trị cùng

foreach(var total in totals) 
{ 
    Console.WriteLine ($"{total.Device} = {total.Total}"); 
} 
------------------ 
Device1 = 45 
Device2 = 5 
Device3 = 5 
5

Bạn có thể làm như thế này:

Dictionary<string, Dictionary<string, int>> _storage = new Dictionary<string, Dictionary<string, int>>(); 
Dictionary<string, int> x = new Dictionary<string, int>(); 
x.Add("x", 2); 
x.Add("z", 2); 
x.Add("y", 2); 
_storage.Add("x", x); 
_storage.Add("z", x); 
_storage.Add("y", x); 

var b = _storage.SelectMany(keyValuePair => keyValuePair.Value) 
     .GroupBy(keyValuePair => keyValuePair.Key) 
     .ToDictionary(valuePairs => valuePairs.Key, grouping => grouping.Sum(kvp => kvp.Value)); 

kết quả sẽ như thế nào: enter image description here

Các vấn đề liên quan