【问题标题】:How to work with nested Arrays and Objects using LINQ如何使用 LINQ 处理嵌套数组和对象
【发布时间】:2019-01-10 16:11:21
【问题描述】:

所以我正在做一个小项目,我在 C# 上使用和反序列化 json 字符串到对象中。我为自己设置了一个业务逻辑,我想搜索一个团队并返回他们的进球数 (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
    }}]

【问题讨论】:

  • Linq 不会给你更好的性能。您仍然需要接触所有这些数据才能获得结果。
  • 在其他新闻中,return goal; 看起来不正确;它会在第一次循环迭代时从函数返回,所以我不知道你是如何从中得到有意义的结果的。
  • @RobertHarvey 你会说这是最好的方法吗?如果有比这更好的方法吗?感谢您的帮助。
  • 我认为,鉴于这段代码是功能性的,只要你提供一个明确的目标,比如简洁,这个问题更适合codereview

标签: c# json performance linq


【解决方案1】:

这似乎需要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 工具可以自动执行此操作。)但结果如此丑陋,没有任何意义。

【讨论】:

    猜你喜欢
    • 2021-12-10
    相关资源
    最近更新 更多