2016-02-28 51 views
2

好的。標題可能有點混亂,但在這裏就是我試圖做LINN中的維恩圖分類

我有一系列的自然數

var series = Enumerable.Range(1, 100) 

現在我想用GroupBy把數到3組,總理的,偶,奇

series.Select(number => { 
       var type = ""; 
       if (MyStaticMethods.IsPrime(number)) 
        { 
        Type = "prime"; 
        } 
       else if (number % 2 == 0) 
        { 
         type = "Even"; 
        } 
       else 
        { 
         type = "Odd"; 
        } 
        return new { Type=type, Number = number }; 
       }).GroupBy(n => n.Type); 

現在上面的查詢會錯過分類素數是偶數或奇數到兩個類別,他們將只是在「原」組。有沒有辦法讓上述選擇產生多個數字?

我可以嘗試類似以下內容,但它需要額外的扁平化序列。

series.Select(number => { 
       var list = new List<int>(); 

       if (MyStaticMethods.IsPrime(number)) 
        { 
         list.Add(new { Type="prime", Number = number }); 
        } 
       if (number % 2 == 0) 
        { 
         list.Add(new { Type="even", Number = number }); 
        } 
       else 
        { 
         list.Add(new { Type="odd", Number = number }); 
        } 
        return list; 
       }) 
       .SelectMany(n => n) 
      .GroupBy(n => n.Type); 

上述代碼解決了我的問題,有沒有更好的方法可以讓我的代碼看起來更「功能性」?

回答

3

您可以在這裏使用linq,但您需要複製可能存在於不同組中的一些值。 GroupBy僅適用於不相交組,因此您需要一種方法來區分2偶數和2素數。你所做的方法基本上是你需要做的,但它可以做得更有效一些。

您可以定義一組可幫助分類數字的類別。您不一定需要定義新類才能使其發揮作用,但它有助於保持事物的清潔和組織。

class Category<T> 
{ 
    public Category(string name, Predicate<T> predicate) 
    { 
     Name = name; 
     Predicate = predicate; 
    } 
    public string Name { get; } 
    public Predicate<T> Predicate { get; } 
} 

然後以組數字,你可以這樣做:

var series = Enumerable.Range(1, 100); 
var categories = new[] 
{ 
    new Category<int>("Prime", i => MyStaticMethods.IsPrime(i)), 
    new Category<int>("Odd", i => i % 2 != 0), 
    new Category<int>("Even", i => i % 2 == 0), 
}; 
var grouped = 
    from i in series 
    from c in categories 
    where c.Predicate(i) 
    group i by c.Name; 
-1

這是使用無功擴展,你會避免重複值一個很好的例子。

在下面的代碼中,「series」只被解析一次,因爲它是Publish()的熱門來源。
實際的解析是在「Connect()」期間完成的。

using System.Reactive.Linq; 

var list = new List<KeyValuePair<string, int>>(); 

var series= Observable.Range(1, 100).Publish(); 
series.Where(e => e % 2 == 0).Subscribe(e=>list.Add(new KeyValuePair<string, int>("Even",e))); 
series.Where(e => e % 2 == 1).Subscribe(e => list.Add(new KeyValuePair<string, int>("Odd", e))); 
series.Where(e => MyStaticMethods.IsPrime(e)).Subscribe(e => list.Add(new KeyValuePair<string, int>("Prime", e))); 
series.Connect(); 

var result = list.GroupBy(n => n.Key);