2015-10-28 81 views
6

我偶然發現了一個有趣的場景,我找不到解決方案。假設我必須找到一個序列中的majorant(至少出現n/2 + 1次的數字,其中n是該序列的大小)。這是我的實現:SingleOrDefault()當序列包含默認值時

public static int FindMajorant(IList<int> numbers) 
{ 
    return numbers 
     .GroupBy(x => x) 
     .Where(g => g.Count() >= numbers.Count/2 + 1) 
     .Select(g => g.Key) 
     .SingleOrDefault(); 
} 

我使用SingleOrDefault(),如果它的序列或類型的默認值中發現它返回的元素:在這種情況下,它會返回0,因爲它是默認值一個int。例如,我的方法按以下順序返回3

List<int> sampleNumbers = new List<int>() { 2, 2, 3, 3, 2, 3, 4, 3, 3 }; 

這是預期的行爲。

但是,如果序列中的majorant爲零(0),會發生什麼情況?它會返回0,但這樣,我怎麼能確定它是否從SingleOrDefault()作爲默認值,或majorant零?也許,我可以使用Single(),但那會拋出一個非常不合理的異常。我也可以發現這個例外,但這對我來說似乎是一種不好的做法。所以我的問題是,處理這種情況的首選方法是什麼?

+3

請注意,你可以拉'numbers.Count/2 + 1'了查詢和到一個變量,以避免爲每一個組重新計算它。 – Servy

+0

@Servy不算'IList '的屬性,所以它實際上並沒有被計算出來? –

+0

@MichaelMcGriff他指的是作爲一個整體的表達。 – arnaudoff

回答

8

使用可爲空的值,其中null表示不存在majorant,而不是使用「0」表示該值。並且足夠方便的是,int?的默認值是null,因此您的代碼所需的唯一更改是在調用SingleOrDefault之前獲得一個可爲空的整數序列。

public static int? FindMajorant(IList<int> numbers) 
{ 
    return numbers 
     .GroupBy(x => x) 
     .Where(g => g.Count() >= numbers.Count/2 + 1) 
     .Select(g => (int?)g.Key) 
     .SingleOrDefault(); 
} 
+0

非常優雅,謝謝。 – arnaudoff

0

你能預料的結果中一個類型的對象說MajorantResult從而然後返回null:

public static MajorantResult FindMajorant(IList<int> numbers) 
    { 
     return numbers 
      .GroupBy(x => x) 
      .Where(g => g.Count() >= numbers.Count/2 + 1) 
      .Select(g => new MajorantResult(g.Key)) 
      .SingleOrDefault(); 
    } 

    public class MajorantResult 
    { 
     public int Key { get; } 

     public MajorantResult(int key) 
     { 
      this.Key = key; 
     } 
    }