如何使用LINQ处理嵌套数组和对象

时间:2019-01-10 16:11:21

标签: c# json performance linq

所以我正在一个小项目上工作,我正在使用json字符串并将其反序列化为C#对象。我设定了自己的业务逻辑,我想寻找一支球队并返回他们进球的数量(https://raw.githubusercontent.com/openfootball/football.json/master/2014-15/en.1.json

问题是我想使用LINQ而不是循环(我的原始方法)返回目标数。但是,我不知道如何获取分数。例如

namespace ConsoleApp
{
class Program
{

    private static string jsonUrl { get; set; } = "https://raw.githubusercontent.com/openfootball/football.json/master/2014-15/en.1.json";
    private static string teamKey { get; set; } = "swansea";
    static void Main()
    {
       var goal = Run(teamKey.ToLower());
       Console.WriteLine(goal);
       Console.ReadKey();
    }

    public static int Run(string team)
    {

        using (var webclient = new WebClient())
        {

            var rawJson = webclient.DownloadString(jsonUrl);

            var jsonModel = JsonConvert.DeserializeObject<RootObject>(rawJson);


            foreach (var rounds in jsonModel.rounds)
            {
                foreach (var match in rounds.matches)
                {
                    var goal = match.team1.key.Equals(teamKey) ? match.score1 : 0;

                    if (goal == 0)
                    {
                        goal = match.team2.key.Equals(teamKey) ? match.score2 : 0;
                    }
                    return goal;
                }
            }


            return 0;
        }

    }
}

public class Team1
{
    public string key { get; set; }
    public string name { get; set; }
    public string code { get; set; }
}

public class Team2
{
    public string key { get; set; }
    public string name { get; set; }
    public string code { get; set; }
}

public class Match
{
    public string date { get; set; }
    public Team1 team1 { get; set; }
    public Team2 team2 { get; set; }
    public int score1 { get; set; }
    public int score2 { get; set; }
}

public class Round
{
    public string name { get; set; }
    public List<Match> matches { get; set; }
}

public class RootObject
{
    public string name { get; set; }
    public List<Round> rounds { get; set; }
}

}

上面的代码成功执行并根据足球队返回正确的进球数。但是我不认为这是最好的方法。 (输入:“ swansea”预期结果:2,实际结果:2)

该数组表示如下:

"rounds": [
{
  "name": "Matchday 1",
"matches": [
    {
      "date": "2014-08-16",
      "team1": {
        "key": "manutd",
        "name": "Manchester United",
        "code": "MUN"
      },
      "team2": {
        "key": "swansea",
        "name": "Swansea",
        "code": "SWA"
      },
      "score1": 1,
      "score2": 2
    },
    {
      "date": "2014-08-16",
      "team1": {
        "key": "leicester",
        "name": "Leicester City",
        "code": "LEI"
      },
      "team2": {
        "key": "everton",
        "name": "Everton",
        "code": "EVE"
      },
      "score1": 3,
      "score2": 5
    }}]

1 个答案:

答案 0 :(得分:0)

这似乎需要from x in y ... select z语法才能获得可读的LINQ。用以下代码替换以foreach (var rounds开头和以return 0;结尾的部分:

return (from round in jsonModel.rounds
from match in round.matches
let goal = match.team1.key.Equals(teamKey) ? match.score1 : 0
select goal == 0 ? (match.team2.key.Equals(teamKey) ? match.score2 : 0) : goal).FirstOrDefault();

为清楚起见,我将其保留为类似于问题中的代码。最好提取辅助方法以使LINQ更具可读性:表达式match.team1.key.Equals(teamKey) ? match.score1 : 0的一个助手,表达式goal == 0 ? (match.team2.key.Equals(teamKey) ? match.score2 : 0) : goal的一个助手。

from x in y ... select z 可以变成LINQ方法链。 (例如ReSharper工具可以自动执行此操作。)但是结果是如此丑陋,没有必要显示。