简体   繁体   中英

JSON iteration based on value using jquery

I'm trying to create a simple display of NBA west leaders in order by seed using the following json file:

http://data.nba.com/data/v2014/json/mobile_teams/nba/2014/00_standings.json

Right now I have the following:

$(document).ready(function() {

$.getJSON('http://data.nba.com/data/v2014/json/mobile_teams/nba/2014/00_standings.json',function(info){

    var eastHead = info.sta.co[0].val;
    var divi = info.sta.co[0].di[0].val;

    /*evaluate East*/
    for(i=0;i < divi.length;i++){

        var visTeam ='<li>' + divi + '</li>';
         document.getElementById("eastHead").innerHTML=eastHead;
    }
    var seed = info.sta.co[0].di[0].t[0].see;


                    $.each(menuItems.data, function (i) {
                        var eastSeed ='<li>' + seed + '</li>';
                        console.log(eastSeed)
                        document.getElementById("eastSeed").innerHTML=eastSeed;
                    });//$.each(menuItems.data, function (i) {

});//getJSON

});//ready

I'm looking just to list out the leaders in order. So right now we have

  1. Golden State
    2. Memphis
    3. Houston
    4. Portland
    5. LA Clippers
    6. Dallas
    .... and so forth.

This is based off of the "see" value which means seed in the west.

This issue is I'm getting a single value rather than an iteration.

Updated:

$(document).ready(function() {

$.getJSON('http://data.nba.com/data/v2014/json/mobile_teams/nba/2014/00_standings.json',function(info){



                    /**************************************************/
                        //Get info above here
                        var westDivision = info.sta.co[1].di;
                        westDivision.forEach(function (subdivision)
                        {
                            subdivision.t.forEach(function (team)
                            {
                                westTeams.push({
                                    city: team.tc,
                                    name: team.tn,
                                    seed: team.see
                                });
                            });
                        });
                        function compare(a,b) {
                          if (a.see < b.see)
                             return -1;
                          if (a.see > b.see)
                            return 1;
                          return 0;
                        }
                        var sorted = westTeams.sort(compare);
                        sorted.forEach(function (el,i)
                        {
                            console.log(i+'. '+el.city+' '+el.name);
                        });
                        /**************************************************/    

});//getJSON

});//ready

console output :

  1. Portland Trail Blazers
  2. Oklahoma City Thunder
  3. Denver Nuggets
  4. Utah Jazz
  5. Minnesota Timberwolves
  6. Golden State Warriors
  7. Los Angeles Clippers
  8. Phoenix Suns
  9. Sacramento Kings
  10. Los Angeles Lakers
  11. Memphis Grizzlies
  12. Houston Rockets
  13. Dallas Mavericks
  14. San Antonio Spurs
  15. New Orleans Pelicans

I like to iterate with forEach. Rather then having to worry about indexes you can directly reference each item of the array.

Using this code you can put the data you want into an array.

//Get info above here
var westTeams = [];
var westDivision = info.sta.co[1].di;

westDivision.forEach(function (subdivision)
{
    subdivision.t.forEach(function (team)
    {
        westTeams.push({
            city: team.tc,
            name: team.tn,
            seed: team.see
        });
    });
});

Then you can sort them using obj.sort

function compare(a,b) {
  if (a.seed < b.seed)
     return -1;
  if (a.seed > b.seed)
    return 1;
  return 0;
}
var sorted = westTeams.sort(compare);

Finally, you can print them in order.

sorted.forEach(function (el,i)
{
    console.log((i+1)+'. '+el.city+' '+el.name);
});

Querying a large JavaScript object graph can be a tedious thing, especially if you want to have dynamic output. Implementing support for different filter criteria, sort orders, "top N" restrictions, paging can be difficult. And whatever you come up with tends to be inflexible.

To cover these cases you can (if you don't mind the learning curve) use linq.js ( reference ), a library that implements .NET's LINQ for JavaScript.

The following showcases what you can do with it. Long post, bear with me.

Preparation

Your NBA data object follows a parent-child hierarchy, but it misses a few essential things:

  • there are no parent references
  • the property that contains the children is called differently on every level (ie co , di , t )

In order to make the whole thing uniform (and therefore traversable), we first need to build a tree of nodes from it. A tree node would wrap objects from your input graph and would look like this:

{
    obj: o,       /* the original object, e.g. sta.co[1]               */
    parent: p,    /* the parent tree node, e.g. the one that wraps sta */
    children: []  /* array of tree nodes built from e.g. sta.co[1].di  */
}

The building of this structure can be done recursively in one function:

function toNode(obj) {
    var node = {
            obj: obj,
            parent: this === window ? null : this,
            // we're interested in certain child arrays, either of:
            children: obj.co || obj.di || obj.t || []
        };

    // recursive step (with reference to the parent node)
    node.children = node.children.map(toNode, node);

    // (*) explanation below
    node.parents = Enumerable.Return(node.parent)
        .CascadeDepthFirst("$ ? [$.parent] : []").TakeExceptLast(1);

    return node;
}

(*) The node.parents property is a convenience facility. It contains an enumeration of all parent nodes except the last one (ie the root node, which is null ). This enumeration can be used for filtering as shown below.

The result of this function is a nice-and-uniform interlinked tree of nodes. (Expand the code snippet, but unfortunately it currently does not run due to same-origin browser restrictions. Maybe there is something in the NBA REST API that needs to be turned on first.)

 function toNode(obj) { var node = { obj: obj, parent: this === window ? null : this, children: obj.co || obj.di || obj.t || [] }; node.children = node.children.map(toNode, node); node.parents = Enumerable.Return(node.parent) .CascadeDepthFirst("$ ? [$.parent] : []").TakeExceptLast(1); return node; } $(function () { var standingsUrl = 'http://data.nba.com/data/v2014/json/mobile_teams/nba/2014/00_standings.json'; $.getJSON(standingsUrl, function(result) { var sta = toNode(result.sta); console.log(sta); }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

Result

Now that we have a fully traversable tree of nodes, we can use LINQ queries to do complex things with only a few lines of code:

// first build our enumerable stats tree
var stats = Enumerable.Return(toNode(result.sta));

// then traverse into children; the ones with a tid are teams
var teams = stats.CascadeDepthFirst("$.children")
    .Where("$.obj.tid");

OK, we have identified all teams, so we can...

// ...select all that have a parent with val 'West' and order them by 'see'
var westernTeams = teams.Where(function (node) {
        return node.parents.Any("$.obj.val === 'West'");
    })
    .OrderByDescending("$.obj.see");

// ...insert the top 5 into our page as list items
westernTeams.Take(5).Do(function (node) {
    $("<li></li>", {text: node.obj.tc + ' ' + node.obj.tn}).appendTo("#topFiveList");
});

// ...turn them as an array of names
var names = westernTeams.Select("$.obj.tc + ' ' + $.obj.tn").ToArray();
console.log(names);

Of course what I have done there in several steps could be done in one:

// request details for all Northwest and Southeast teams who have won more than one game (*)
var httpRequests = Enumerable.Return(toNode(result.sta))
    .CascadeDepthFirst("$.children")
    .Where("$.obj.tid")
    .Where(function (node) {
        var str = node.obj.str.split(" ");
        return str[0] === "W" && str[1] > 1 && 
            node.parents.Any("$.obj.val==='Northwest' || $.obj.val==='Southeast'");
    })
    .Select(function (node) {
        return $.getJSON(detailsUrl, {tid: node.obj.tid});
    })
    .ToArray();

$.when.apply($, httpRequests).done(function () {
    var results = [].slice.call(arguments);
    // all detail requests have been fetched, do sth. with the results
});

(*) correct me if I'm wrong, I have no idea what the data in the JSON file actually means

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM