2015-10-28 15 views
6

Mi sono imbattuto in uno scenario interessante, a cui non sono riuscito a trovare una soluzione. Supponiamo di dover trovare il majorant in una sequenza (il numero che si verifica almeno n/2 + 1 volte, dove n corrisponde alla dimensione della sequenza). Questa è la mia realizzazione:SingleOrDefault() quando la sequenza contiene il valore predefinito

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(); 
} 

sto usando SingleOrDefault(), che restituisce l'elemento se è trovato nella sequenza o il valore di default per il tipo: in questo caso, verrà restituito 0 in quanto è il valore predefinito per un int. Ad esempio, il mio metodo restituisce 3 per la seguente sequenza:

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

, che è il comportamento previsto.

Tuttavia, cosa succede se il majorante nella sequenza è zero (0)? Restituirebbe 0, ma in questo modo, come potrei determinare se è lo zero da SingleOrDefault() come valore predefinito o il majorant? Forse, potrei usare Single(), ma ciò creerebbe un'eccezione che è praticamente incorrente. Potrei anche cogliere questa eccezione, ma mi sembra una cattiva pratica. Quindi la mia domanda è, qual è il modo preferito per gestire questa situazione?

+3

Nota che si può tirare 'numbers.Count/2 + 1' fuori della query e in una variabile per evitare di ricalcolarlo per ogni singolo gruppo. – Servy

+0

@Servy non è 'Count' una proprietà di' IList 'quindi non viene effettivamente calcolato? –

+0

@MichaelMcGriff Si riferisce all'espressione nel suo insieme. – arnaudoff

risposta

8

Utilizzare un valore Null in cui null indica che non è presente alcun majorant, piuttosto che utilizzare "0" per indicare ciò. E convenientemente, il valore predefinito di int? è null, quindi l'unica modifica necessaria al codice è ottenere una sequenza di valori nullable prima di chiamare 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

Molto elegante, grazie. – arnaudoff

0

Si potrebbe proiettare il risultato in un oggetto tipizzato dire MajorantResult così poi tornare nulla:

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; 
     } 
    } 
Problemi correlati