2012-06-22 2 views
7

Mi è stata fornita la seguente domanda .NET in un'intervista. Non so perché ho ottenuto voti bassi. Purtroppo non ho ricevuto un feedback.Intervista .NET, struttura del codice e il design

Domanda:

Il file hockey.csv contiene i risultati del Hockey Premier League. Le colonne "For" e "Contro" contengono il numero totale di goal segnati a favore e contro ciascuna squadra in quella stagione (quindi Alabama ha segnato 79 gol contro avversari e ha segnato 36 gol contro di loro).

Scrivere un programma per stampare il nome della squadra con la differenza più piccola tra gli obiettivi "for" e "contro".

la struttura del hockey.csv assomiglia a questo (si tratta di un file CSV valida, ma ho appena copiato i valori qui per farvi un'idea)

Team - Per - Contro

Alabama 79 36

Washinton 67 30

Indiana 87 45

Newcastle 74 52

Florida 53 37

New York 46 47

Sunderland 29 51

Lova 41 64

Nevada 33 63

Boston 30 64

Nevada 33 63

Boston 30 64

Soluzione:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string path = @"C:\Users\<valid csv path>"; 

     var resultEvaluator = new ResultEvaluator(string.Format(@"{0}\{1}",path, "hockey.csv")); 
     var team = resultEvaluator.GetTeamSmallestDifferenceForAgainst(); 

     Console.WriteLine(
      string.Format("Smallest difference in ‘For’ and ‘Against’ goals > TEAM: {0}, GOALS DIF: {1}", 
      team.Name, team.Difference)); 

     Console.ReadLine(); 
    } 
} 

public interface IResultEvaluator 
{ 
    Team GetTeamSmallestDifferenceForAgainst(); 
} 

public class ResultEvaluator : IResultEvaluator 
{ 
    private static DataTable leagueDataTable; 
    private readonly string filePath; 
    private readonly ICsvExtractor csvExtractor; 

    public ResultEvaluator(string filePath){ 
     this.filePath = filePath; 
     csvExtractor = new CsvExtractor(); 
    } 

    private DataTable LeagueDataTable{ 
     get 
     { 
      if (leagueDataTable == null) 
      { 
       leagueDataTable = csvExtractor.GetDataTable(filePath); 
      } 

      return leagueDataTable; 
     } 
    } 

    public Team GetTeamSmallestDifferenceForAgainst() { 
     var teams = GetTeams(); 
     var lowestTeam = teams.OrderBy(p => p.Difference).First(); 
     return lowestTeam; 
    } 

    private IEnumerable<Team> GetTeams() { 
     IList<Team> list = new List<Team>(); 

     foreach (DataRow row in LeagueDataTable.Rows) 
     { 
      var name = row["Team"].ToString(); 
      var @for = int.Parse(row["For"].ToString()); 
      var against = int.Parse(row["Against"].ToString()); 
      var team = new Team(name, against, @for); 
      list.Add(team); 
     } 

     return list; 
    } 
} 

public interface ICsvExtractor 
{ 
    DataTable GetDataTable(string csvFilePath); 
} 

public class CsvExtractor : ICsvExtractor 
{ 
    public DataTable GetDataTable(string csvFilePath) 
    { 
     var lines = File.ReadAllLines(csvFilePath); 

     string[] fields; 

     fields = lines[0].Split(new[] { ',' }); 
     int columns = fields.GetLength(0); 
     var dt = new DataTable(); 

     //always assume 1st row is the column name. 
     for (int i = 0; i < columns; i++) 
     { 
      dt.Columns.Add(fields[i].ToLower(), typeof(string)); 
     } 

     DataRow row; 
     for (int i = 1; i < lines.GetLength(0); i++) 
     { 
      fields = lines[i].Split(new char[] { ',' }); 

      row = dt.NewRow(); 
      for (int f = 0; f < columns; f++) 
       row[f] = fields[f]; 
      dt.Rows.Add(row); 
     } 

     return dt; 
    } 
} 

public class Team 
{ 
    public Team(string name, int against, int @for) 
    { 
     Name = name; 
     Against = against; 
     For = @for; 
    } 

    public string Name { get; private set; } 

    public int Against { get; private set; } 

    public int For { get; private set; } 

    public int Difference 
    { 
     get { return (For - Against); } 
    } 
} 

uscita: più piccola differenza in for' and contro' obiettivi> TEAM: Boston, OBIETTIVI DIF: -34

Può qualcuno si prega di consultare il mio codice e vedere qualcosa ovviamente sbagliato qui? Erano interessati solo alla struttura/design del codice e se il programma produce il risultato corretto (cioè la differenza più bassa). Molto apprezzato.

+3

Come fai a sapere che hai ottenuto un punteggio basso se non hai ricevuto alcun feedback? A volte qualche altra persona si adatta meglio alla posizione, tutto qui. –

+0

Per curiosità. Quanto tempo ti hanno dato per completare questa domanda? –

+0

@ClaudioRedi è anche quello che mi sorprende, mi hanno appena dato un voto basso e non hanno avuto successo in questa fase. Non ho detto perché. –

risposta

6

Credo che si dimentica capito la domanda. L'intervistatore ha chiesto la differenza minima tra obiettivi "for" e "contro" e il tuo programma sta calcolando la media obiettivo migliore. Se vedi la differenza minima, allora è New York non Boston. Vorrei aggiornare il codice fenix2222 qui.

var teamRecords = File.ReadAllLines(Path.Combine(Application.StartupPath,"teams.csv")); 
      var currentLow = int.MaxValue; //just to make sure that difference is initially less than currentLow. 
      foreach (var record in teamRecords.Skip(1).ToList()) 
      { 
       var tokens = record.Split(','); 
       if (tokens.Length == 3) 
       { 
        int forValue = 0; 
        int againstValue = 0; 

        if (int.TryParse(tokens[1], out forValue) && int.TryParse(tokens[2], out againstValue)) 
        { 
         var difference = 0; 
         if (forValue > againstValue) 
          difference = forValue - againstValue; 
         else 
          difference = againstValue - forValue; 

         if (difference < currentLow) 
          currentLow = difference; 
        } 
       } 
      } 
+0

Perché non usi semplicemente difference = Math.Abs ​​(forValue - againstValue). Ma ho capito, stavo scrivendo il mio codice basato sui commenti di j_lewis. Ho aggiornato il mio codice – fenix2222

+0

sì fuori corso, grazie. ero solo di fretta per mettere i miei pensieri qui :) – ABH

+2

+1 per il buon pick-up – fenix2222

11

Forse perché hai scritto tante righe di codice, quando può essere solo

var teamRecords = File.ReadAllLines("path"); 
var currentLow = int.MaxValue; 
foreach (var record in teamRecords.Skip(1).ToList()) 
{ 
    var tokens = record.Split(','); 
    if (tokens.Length == 3) 
    { 
     int forValue = 0; 
     int againstValue = 0; 

     if (int.TryParse(tokens[1], out forValue) && int.TryParse(tokens[2], out againstValue)) 
     { 
      var difference = Math.Abs(forValue - againstValue); 
      if (difference < currentLow) currentLow = difference; 
     } 
    } 
} 

Console.WriteLine(currentLow); 
+0

Stavo per dire una cosa simile --- perché doveva includere un'interfaccia, un DataTable e così via? Quindi, ancora una volta, non potrei scrivere nulla di buono come te, quindi cosa ne so :) – CptSupermrkt

+0

Concordato. @ j_lewis la tua lettura CSV è stata inutilmente lunga. Sospetto che stessero cercando una risposta breve con concetti OO limitati. –

+0

Se si aspettavano l'uso dell'ereditarietà e del polimorfismo che avrebbero detto così e probabilmente hanno dato una domanda un po 'diversa. Non è comune creare un'infrastruttura così grande solo per leggere qualche file csv. L'efficienza del codice originale è piuttosto negativa. – fenix2222

3

solo alcune delle cose da una visione superficiale:

  1. Ci sono 2 interfacce, ma non v'è alcun valore in uno dei loro usi.
  2. Non vi è alcun motivo valido per introdurre un DataTable nell'istruzione del problema.
  3. Il codice è eccessivamente complesso.
  4. L'uso di IList e IEnumerable nel metodo GetTeams sembra essere utilizzato 'solo perché'.
  5. La classe ResultEvaluator non è riutilizzabile, vale a dire, non appena si istanzia la classe, non è mai possibile reimpostare il file csv. Puoi continuare a chiamare lo stesso metodo (GetTeamSmallestDifferenceForAgainst) più e più volte; non sono disponibili altre proprietà pubbliche.
  6. Nel metodo GetDataTable, i campi stringa [] vengono dichiarati su una riga e quindi il valore viene impostato sulla riga successiva.
  7. Ci sono meno di zero ragioni per utilizzare il simbolo @ per il parametro "per" nel costruttore della classe Team; basta rinominare la parola riservata 'per' per qualcos'altro.
  8. Esistono molti costrutti da 3.5+ .NET che potrebbero essere utilizzati per risolvere il problema molto più facilmente; questo mostra solo una mancanza di comprensione della lingua.

Dagli sguardi, sembra davvero che stavate cercando di mostrare che sapevate molto più di quello che veniva chiesto nella dichiarazione del problema. Ma come la conoscenza che conoscevi viene usata in questo esercizio è piuttosto spaventosa, e non in senso positivo.

In futuro, consiglierei di risolvere il problema e non pensarlo troppo. Mantienilo semplice.

+0

1+ per la soluzione. Sono d'accordo che potrei essere troppo complicato. Grazie :) –