【问题标题】:.NET interview, code structure and the design.NET 面试、代码结构和设计
【发布时间】:2012-06-22 03:12:25
【问题描述】:

在一次采访中,我收到了以下 .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' andagainst' 目标的最小差异 > 球队:波士顿,目标 DIF:-34

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

【问题讨论】:

  • 如果您没有收到任何反馈,您怎么知道您得到了低分?有时其他人更适合这个职位,仅此而已。
  • 出于好奇。他们给了你多长时间来完成这个问题?
  • @ClaudioRedi 这也让我感到惊讶,他们只是给了我低分并说在这个阶段不成功。没说为什么。
  • @astroboy 他们最多给了我 2 小时。我只用了一个多小时就完成了。
  • 可能他们不明白你在这里做什么。

标签: c# code-structure


【解决方案1】:

也许是因为你写了这么多行代码,什么时候就可以了

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

【讨论】:

  • 我正要说类似的事情 --- 为什么它必须包含一个接口、一个 DataTable 等等?再说一次,我写的东西几乎没有你写的那么好,所以我知道什么:)
  • 同意。 @j_lewis 您的 csv 读数过长。怀疑他们正在寻找具有有限 OO 概念的简短答案。
  • 如果他们期望使用继承和多态性,那会这样说并且可能会给出一些不同的问题。创建这么大的基础设施只是为了读取一些 csv 文件并不常见。原代码效率很差。
  • Thanjks @CptSupermrkt 和 asto boy,同意 csv 阅读可以缩短一点。 CptSupermrkt,fenix2222 - 我只是想让我的解决方案可测试。这就是我引入接口的原因,所以可以单独测试。
  • @j_lewis,无论如何,如果我在面试,使用DataTable真的皱起眉头。对一个相当复杂和令人担忧的 API 似乎完全没有必要和不必要的依赖。特别是,int.Parse 的所有内容似乎都强烈表明选择了错误的数据结构。
【解决方案2】:

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

【讨论】:

  • 你为什么不直接使用差异 = Math.Abs​​(forValue - againstValue)。但我明白你的意思,我正在编写基于 j_lewis cmets 的代码。我已经更新了我的代码
  • 是的,偏离航线,谢谢。我只是急着把我的想法放在这里:)
【解决方案3】:

粗略的概述中的几件事:

  1. 有 2 个接口,但没有任何用途。
  2. 在问题陈述中引入 DataTable 的理由为零。
  3. 代码过于复杂。
  4. 在 GetTeams 方法中使用 IList 和 IEnumerable 看起来“只是因为”。
  5. ResultEvaluator 类不可重用,即,一旦实例化该类,就永远无法重新设置 csv 文件。您只能一遍又一遍地调用相同的方法(GetTeamSmallestDifferenceForAgainst);没有其他可用的公共属性。
  6. 在 GetDataTable 方法中,string[] 字段在一行中声明,然后在下一行设置值。
  7. 在 Team 类的构造函数中使用 @ 符号作为“for”参数的理由少于零;只需将保留字“for”重命名为其他名称即可。
  8. 3.5+ .NET 中的许多构造可用于更轻松地解决问题;这只是表明缺乏对语言的理解。

从外观上看,您确实试图表明您比问题陈述中所要求的要多得多。但是,你所知道的知识在这个练习中是如何被使用的,这很可怕,而且不是很好。

以后,我建议只解决手头的问题,不要想太多。保持简单。

【讨论】:

  • 1+ 为您的解决方案。我同意我可能过于复杂。谢谢 :)
猜你喜欢
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-28
  • 1970-01-01
相关资源
最近更新 更多