2014-03-13 81 views
1

我需要通過枚舉值得到一個總和。看到這個例子:C#LINQ的總和

在這種來源:

namespace ConsoleApplication 
{ 
    enum fruits { Orange, Grape, Papaya } 

    class item 
    { 
     public fruits fruit; 
     public string foo; 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      item[] list = new item[] 
      { 
       new item() { fruit = fruits.Orange, foo = "afc" }, 
       new item() { fruit = fruits.Orange, foo = "dsf" }, 
       new item() { fruit = fruits.Orange, foo = "gsi" }, 
       new item() { fruit = fruits.Orange, foo = "jskl" }, 
       new item() { fruit = fruits.Grape, foo = "mno" }, 
       new item() { fruit = fruits.Grape, foo = "pqu" }, 
       new item() { fruit = fruits.Grape, foo = "tvs" }, 
      }; 

      var vTotals = from... //Here 


     } 
    } 
} 

我想vTotals是類型

Dictionary<fruits, int> 

的 與價值觀

{ 
    { fruits.Orange, 4 } 
    { fruits.Grape, 3 } 
    { fruits.Papaya, 0 } 
} 

我該怎麼辦呢與Linq?

在此先感謝

回答

3

你想在這裏做什麼在邏輯上是一個組加入。你想用表示每個水果的序列來表示這個表,然後計算這些組的大小。

var totals = Enum.GetValues(typeof(fruits)).OfType<fruits>() 
    .GroupJoin(list, 
     fruit => fruit, 
     item => item.fruit, 
     (fruit, group) => new { Key = fruit, Value = group.Count() }) 
    .ToDictionary(pair => pair.Key, pair => pair.Value); 
+0

完美!!!這正是我需要的! – Riera

3

您可以使用組加入所有的水果種類與項目:

var vTotals = from fruits f in Enum.GetValues(typeof(fruits)) 
       join i in list on f equals i.fruit into g 
       select new { 
       Fruit = f, 
       Count = g.Count() 
       }; 

結果:

[ 
    { Fruit: "Orange", Count: 4 }, 
    { Fruit: "Grape", Count: 3 }, 
    { Fruit: "Papaya", Count: 0 } 
] 
+0

我不認爲這會包括papayas –

+1

@selsman22你爲什麼這麼認爲? –

+1

@ Selman22它會的。一個'GroupJoin'將始終有與第一個集合中的項目一樣多的條目。 – Servy

0

下面是做到這一點的方法之一。它可能不會被認爲是漂亮,做這一切在一個查詢,但它(IMO)明確:(代碼感謝D Stanley,誰因爲刪掉了他的答案的第一部分)

var vTotals = list.GroupBy(i => i.fruit) 
       .ToDictionary(g => g.Key, g => g.Count()); 
foreach (var fruit in Enum.GetValues(typeof(fruits)).Cast<fruits>() 
          .Where(x => !vTotals.ContainsKey(x))) 
{ 
    vTotals.Add(fruit, 0); 
} 
0
var total = from e in Enum.GetValues(typeof(fruits)).OfType<fruits>() 
       select new 
       { 
        Fruit = e, 
        Count = list.Where(f => f.fruit == e).Count() 
       }; 
+1

這比兩個最好的答案效率低很多,因爲你正在爲第一個項目的第二個集合進行線性搜索。 – Servy

-1

這應該這樣做

var vTotals = list.GroupBy(item => item.fruit) 
      .Select(item => Tuple.Create(item.Key, item.Count())) 
      .ToDictionary(key => key.Item1, value => value.Item2); 

這裏我們簡單的組的水果名字與他們的計數,後來把它變成一本字典

+1

這不包括木瓜。 – Servy

0

從@ Servy的回答,如果你想單元測試它,使用MSTest的。

[TestClass] 
public class DummyTests { 
    [TestMethod] 
    public void GroupCountByFruitType() { 
     // arrange 
     var expected = new Dictionary<Fruits, int>() { 
      { Fruits.Grape, 3 } 
      , { Fruits.Orange, 4 } 
      , { Fruits.Papaya, 0 } 
     }; 

     Item[] list = new Item[] { 
      new Item() { Fruit = Fruits.Orange, Foo = "afc" }, 
      new Item() { Fruit = Fruits.Orange, Foo = "dsf" }, 
      new Item() { Fruit = Fruits.Orange, Foo = "gsi" }, 
      new Item() { Fruit = Fruits.Orange, Foo = "jskl" }, 
      new Item() { Fruit = Fruits.Grape, Foo = "mno" }, 
      new Item() { Fruit = Fruits.Grape, Foo = "pqu" }, 
      new Item() { Fruit = Fruits.Grape, Foo = "tvs" } 
     }; 

     // act 
     var actual = Enum.GetValues(typeof(Fruits)).OfType<Fruits>() 
      .GroupJoin(list 
       , fruit => fruit 
       , item => item.Fruit 
       , (fruit, group) => new { Key = fruit, Value = group.Count() }) 
      .ToDictionary(pair => pair.Key, pair => pair.Value);    

     // assert 
     actual.ToList() 
      .ForEach(item => Assert.AreEqual(expected[item.Key], item.Value)); 
    } 

    private class Item { 
     public Fruits Fruit { get; set; } 
     public string Foo { get; set; } 
    } 

    private enum Fruits { 
     Grape, 
     Orange, 
     Papaya 
    } 
} 
+0

如果實際實現是'var actual = new Dictionary ();'它會超過你的測試。我也並不真正看到如何發佈一個現有答案的簡單測試案例真的是對這個問題的答案。 – Servy

+0

@Servy:是的。我只是因爲.NET慣例而使用了大寫字母。 OP還不如使用小型箱。爲了讓你知道,我+1你的答案,因爲我從來沒有用Linq這種方式分組。我以某種方式看到了新的東西。 =) –