简体   繁体   中英

Traverse nested object in a particular way

I need to traverse a tree in a way that I don't know how to do it. I have an object that represents a tournament that have nested objects inside which are the matches to play. So I have 7 objects in total, the first one represents the FINAL that have two children which are the SEMIFINALS that have two more children each that are the QUARTERFINALS. It looks like this:

Match {
  player1: undefined,
  player2: undefined,
  childrenLeft: 
   Match {
     player1: undefined,
     player2: undefined,
     childrenLeft: 
      Match {
        player1: 'John',
        player2: 'Luke',
        childrenLeft: undefined,
        childrenRight: undefined },
     childrenRight: 
      Match {
        player1: 'Ann',
        player2: 'Mark',
        childrenLeft: undefined,
        childrenRight: undefined } },
  childrenRight: 
   Match {
     player1: undefined,
     player2: undefined,
     childrenLeft: 
      Match {
        player1: 'George',
        player2: 'Mary',
        childrenLeft: undefined,
        childrenRight: undefined },
     childrenRight: 
      Match {
        player1: 'Sofie',
        player2: 'Tom',
        childrenLeft: undefined,
        childrenRight: undefined } 
   } 
}

The players on the final and semifinals are undefined because we haven't played the quarterfinals yet.

Then I have a function that tells the computer who won the match so the player advances to the next round. Works fine. And finally I have a function that returns me which is the next match to play that looks like this:

Match.prototype.nextMatch = function () {
if (this.player1 && this.player2) return this;
if (!this.player2 && this.childrenRight !== undefined) return this.childrenRight.nextMatch();
if (!this.player1 && this.childrenLeft !== undefined) return this.childrenLeft.nextMatch();
}

The function works but not in the way I want because it returns me all the games on the right side until one player reaches the final and then it returns me the players from the left side.

I would like that the function returns me the 4th quarterfinal first, then the 3rd quarterfinal, then the 2nd quarterfinal, then the 1st quarterfinal, then the second semifinal, then the first semifinal and, at the end, the final.

If anyone knows how to do it I would appreciate any help!

You could use this function, which has a separate recursion function for tracking the depth in the tree, and so deciding if a potential match is deeper in the tree than the one that was found so far. This way you are sure to get a match that is deepest in the tree:

Match.prototype.nextMatch = function () {
    var next, nextDepth = -1;

    (function recurse(match, depth = 0) {
        if (match.player1 && match.player2 && depth > nextDepth) {
            next = match;
            nextDepth = depth;
        }
        if (!match.player1 && match.childrenLeft)
            recurse(match.childrenLeft, depth + 1);
        if (!match.player2 && match.childrenRight) 
            recurse(match.childrenRight, depth + 1);
    })(this);
    return next;
}

In the demo below, Mary and Ann could play the "right-side" semi-finals, but as there are still games to play in the quarter finals, the function will return one of those, and not the one for Mary and Ann:

 function Match(p1, p2) { this.player1 = p1; this.player2 = p2; this.childrenLeft = undefined; this.childrenRight = undefined; } Match.prototype.nextMatch = function () { var next, nextDepth = -1; (function recurse(match, depth = 0) { if (match.player1 && match.player2 && depth > nextDepth) { next = match; nextDepth = depth; } if (!match.player2 && match.childrenRight) recurse(match.childrenRight, depth + 1); if (!match.player1 && match.childrenLeft) recurse(match.childrenLeft, depth + 1); })(this); return next; } var root = new Match(); root.childrenRight = new Match('Mary', 'Ann'); root.childrenLeft = new Match(); root.childrenLeft.childrenLeft = new Match('George', 'Mary'); root.childrenLeft.childrenRight = new Match('Sophie', 'Tom'); var nextMatch = root.nextMatch(); console.log('Next match: ', nextMatch.player1, nextMatch.player2); 

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