2012-06-22 9 views
7

Me han dado la siguiente pregunta .NET en una entrevista. No sé por qué tengo bajas calificaciones. Lamentablemente no recibí ningún comentario.Entrevista .NET, estructura de código y el diseño

Pregunta:

El hockey.csv archivo contiene los resultados de la Premier League de hockey. Las columnas 'Por' y 'Contra' contienen el número total de goles marcados a favor y en contra de cada equipo en esa temporada (por lo que Alabama anotó 79 goles contra oponentes, y anotó 36 goles en contra de ellos).

Escriba un programa para imprimir el nombre del equipo con la menor diferencia en los objetivos "a favor" y "en contra".

la estructura de la hockey.csv se parece a esto (que es un archivo CSV válido, pero acabo de copiar los valores aquí para tener una idea)

equipo - Para - Contra

Alabama 79 36

Washinton 67 30

Indiana 87 45

Newcastle 74 52

Florida 53 37

Nueva York 46 47

Sunderland 29 51

Lova 41 64

Nevada 33 63

Boston 30 64

Nevada 33 63

Boston 30 64

Solución:

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

Salida: La diferencia más pequeña en for' and contra objetivos'> Equipo: Boston, OBJETIVOS DIF: -34

Puede alguien por favor revisar mi código y ver algo obviamente mal aquí? Solo estaban interesados ​​en la estructura/diseño del código y si el programa produce el resultado correcto (es decir, la diferencia más baja). Muy apreciado.

+3

¿Cómo sabes que tienes bajas calificaciones si no recibes ningún comentario? A veces, otra persona simplemente se adapta mejor para el puesto, eso es todo. –

+0

Por curiosidad. ¿Cuánto tiempo te dieron para completar esta pregunta? –

+0

@ClaudioRedi eso es lo que también me sorprende, simplemente me dieron mala nota y dijeron que no tuvieron éxito en esta etapa. No dije por qué. –

Respuesta

6

supongo que la falta entendía la pregunta. El entrevistador preguntó la diferencia mínima entre los objetivos "a favor" y "en contra" y su programa calcula el mejor promedio de objetivos. Si ve la diferencia mínima, entonces es Nueva York no Boston. Permítanme actualizar el código fenix2222 aquí.

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

¿Por qué no usa simplemente difference = Math.Abs ​​(forValue - againstValue). Pero entiendo su punto, estaba escribiendo mi código basado en los comentarios de j_lewis. He actualizado mi código – fenix2222

+0

sí fuera del curso, gracias. Tenía prisa para poner mis pensamientos aquí :) – ABH

+2

+1 para la buena recogida – fenix2222

11

Tal vez porque usted escribió tantas líneas de código, cuando puede ser sólo

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

Iba a decir algo similar --- ¿por qué tenía que incluir una interfaz, una DataTable, etc.? Por otra parte, no pude escribir nada tan bueno como tú, así que sé :) – CptSupermrkt

+0

De acuerdo. @j_lewis su lectura de csv fue innecesariamente larga. Sospecho que estaban buscando respuestas cortas con conceptos OO limitados. –

+0

Si esperaban el uso de la herencia y el polimorfismo, eso lo hubiera dicho y probablemente le haya dado una pregunta algo diferente. No es común crear una infraestructura tan grande solo para leer algún archivo csv. La eficiencia del código original es bastante mala. – fenix2222

3

Sólo un par de cosas a partir de una visión superficial:

  1. Hay 2 interfaces, pero no hay valor en cualquiera de sus usos.
  2. No hay ninguna razón para introducir una DataTable en la instrucción del problema.
  3. El código es excesivamente complejo.
  4. El uso de IList e IEnumerable en el método GetTeams parece que se utilizará 'solo porque'.
  5. La clase ResultEvaluator no es reutilizable, es decir, tan pronto como crea una instancia de la clase, nunca puede volver a establecer el archivo csv. Solo puede seguir llamando al mismo método (GetTeamSmallestDifferenceForAgainst) una y otra vez; no hay otras propiedades públicas disponibles.
  6. En el método GetDataTable, los campos de cadena [] se declaran en una línea y luego el valor se establece en la línea siguiente.
  7. Hay menos de cero razones para usar el símbolo @ para el parámetro 'para' en el constructor de la clase de equipo; simplemente cambie el nombre de la palabra reservada 'por' a otra cosa.
  8. Hay muchas construcciones de 3.5+ .NET que se podrían usar para resolver el problema mucho más fácilmente; esto solo muestra una falta de comprensión del idioma.

Por lo que parece, parece que intentabas demostrar que sabías bastante más de lo que se preguntaba en el enunciado del problema. Pero, cómo el conocimiento que usted sabía que se está utilizando en este ejercicio es bastante aterrador, y no en el buen sentido.

En el futuro, recomendaría resolver el problema y no pensar demasiado. Mantenlo simple.

+0

1+ para su solución. Estoy de acuerdo en que podría haberme complicado demasiado. Gracias :) –

Cuestiones relacionadas