7

在一次采访中,我收到了以下 .NET 问题。我不知道为什么我的分数很低。不幸的是,我没有得到反馈。

问题:

文件 hockey.csv 包含曲棍球超级联赛的结果。“For”和“Against”列包含该赛季每支球队的进球总数(因此,阿拉巴马队对阵对手打进79球,对阵对手打进36球)。

编写一个程序,打印出“支持”和“反对”目标差异最小的团队的名称。

hockey.csv 的结构看起来像这样(它是一个有效的 csv 文件,但我只是复制了这里的值来了解一下)

团队 - 支持 - 反对

阿拉巴马州 79 36

华盛顿 67 30

印第安纳州 87 45

纽卡斯尔 74 52

佛罗里达州 53 37

纽约 46 47

桑德兰 29 51

洛娃 41 64

内华达州 33 63

波士顿 30 64

内华达州 33 63

波士顿 30 64

解决方案:

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

输出:对目标的最小差异for' and> 球队:波士顿,目标 DIF:-34

有人可以查看我的代码并在这里看到任何明显错误的地方吗?他们只对代码的结构/设计以及程序是否产生正确的结果(即最低差异)感兴趣。非常感激。

4

3 回答 3

11

也许是因为你写了这么多行代码,当它可以只是

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);
于 2012-06-22T03:24:59.770 回答
6

我猜你错过了理解这个问题。面试官询问“支持”和“反对”目标之间的最小差异,您的程序正在计算最佳目标平均值。如果您看到最小的差异,那么它是纽约而不是波士顿。让我在这里更新fenix2222代码。

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;
                    }
                }
            }
于 2012-06-22T04:46:10.713 回答
3

Just a few things from a cursory overview:

  1. There are 2 interfaces, but there is no value in either of their uses.
  2. There is zero reason to introduce a DataTable to the problem statement.
  3. The code is overly-complex.
  4. The use of IList and IEnumerable in the GetTeams method look to be used 'just because'.
  5. The ResultEvaluator class is not reusable, i.e., as soon as you instantiate the class, you can never re-set the csv file. You can only keep calling the same method (GetTeamSmallestDifferenceForAgainst) over and over; no other public properties are available.
  6. In the GetDataTable method, the string[] fields is declared on one line and then the value is set on the next line.
  7. There is less than zero reasons to use the @ symbol for the 'for' paramater in the Team class' constructor; just rename the reserved word 'for' to something else.
  8. There are many constructs from 3.5+ .NET that could be used to solve the problem much easier; this just shows a lack of understanding of the language.

From the looks, it really appears you were trying to show you knew quite a bit more than what was being asked in the problem statement. But, how the knowledge you knew is being used in this exercise is quite scary, and not in a good way.

In the future, I'd recommend just solving the problem at hand and don't over-think it. Keep it simple.

于 2012-06-22T04:57:57.480 回答