2017-04-08 72 views
3

鑑於各種口袋妖怪戰鬥的JSON:地圖關係對象

[ 
    { 
     "battleID": "1", 
     "trainers": [ 
      { 
       "LastName": "Ketchum", 
       "ForeName": "Ash" 
     }, 
      { 
       "LastName": "Mason", 
       "ForeName": "Misty" 
     } 
    ] 
    }, 
    { 
     "battleID": "2", 
     "trainers": [ 
      { 
       "LastName": "Mason", 
       "ForeName": "Misty" 
     }, 
      { 
       "LastName": "Brock", 
       "ForeName": "Stuart" 
     }, 
      { 
       "LastName": "Ian", 
       "ForeName": "Foster" 
     } 
    ] 
    }, 
    { 
     "battleID": "3", 
     "trainers": [ 
      { 
       "LastName": "Brock", 
       "ForeName": "Stuart" 
     }, 
      { 
       "LastName": "Ketchum", 
       "ForeName": "Ash" 
     } 
    ] 
    } 
] 

我要地圖網格清點2寵物小精靈訓練師/玩家之間匹配的數目。一場比賽最多可同時擁有4名選手。

  Ash Ketchum  Misty Mason  Brock Stuart  Ian Foster 
Ash Ketchum  2    1    1     0 

Misty Mason  1    2    1     1 

Brock Stuart  1    1    2     1 

Ian Foster  0    1    1     1 

我的代碼:

class Trainer { 
constructor(firstname, lastname) { 
    this.firstname = firstname; 
    this.lastname = lastname; 
} 

coBattles(trainer) { 
    var battles = 0; 
    jsonData.map(x => { 
     x.trainers.map(y => { 
      if (this.firstname === y.ForeName && this.lastname === y.LastName) { 
       x.trainers.map(z => { 
        if (trainer.firstname === z.ForeName && trainer.lastname === z.LastName) 
         battles++; 
       }); 
      } 
     }); 
    }); 
    return battles; 
} 

}

var pokemonTrainers = []; 

// Currently Undesirable as I want a 'unique' array of all participating trainers. 
jsonData.forEach(x => { 
    x.trainers.forEach(y => { 
     var trainer = new Trainer(y.ForeName, y.LastName); 
     pokemonTrainers.push(trainer); 
    }); 
}); 

//Battles between Misty Mason and Brock Stuart 
console.log(pokemonTrainers[1].coBattles(pokemonTrainers[3])); 
//returns 1 

我找的,如果我能在香草JS /與第三方庫這樣做更好的建議。我怎樣才能使這個效率足以處理大量的戰鬥數據(百萬)。

+0

只是一個評論,Array.map/forEach以及在V8循環其他內置函數目前比普通的要慢(Chrome和節點,JS) –

回答

0

你可以先把所有的唯一玩家的名字,然後建立對象的每個球員,作爲一個值與每個球員,包括他自己的名字另一個對象。然後你只需要循環你的數據並增加該對象的值,最後建立表格。

var data = [{"battleID":"1","trainers":[{"LastName":"Ketchum","ForeName":"Ash"},{"LastName":"Mason","ForeName":"Misty"}]},{"battleID":"2","trainers":[{"LastName":"Mason","ForeName":"Misty"},{"LastName":"Brock","ForeName":"Stuart"},{"LastName":"Ian","ForeName":"Foster"}]},{"battleID":"3","trainers":[{"LastName":"Brock","ForeName":"Stuart"},{"LastName":"Ketchum","ForeName":"Ash"}]}] 
 

 
var players = {} 
 
var result = {} 
 

 
// Get all names 
 
data.forEach(function(e) { 
 
    e.trainers.forEach(function(p) { 
 
    players[p.LastName + ' ' + p.ForeName] = 1 
 
    }) 
 
}) 
 

 
// Add to result object 
 
Object.keys(players).forEach(function(name) { 
 
    Object.keys(players).forEach(function(e) { 
 
    result[name] = Object.assign(result[name] || {}, {[e]: 0}) 
 
    }) 
 
}) 
 

 
// Increment values 
 
data.forEach(function(e) { 
 
    e.trainers.forEach(function(a, j) { 
 
    e.trainers.forEach(function(c, i) { 
 
     result[a.LastName + ' ' + a.ForeName][c.LastName + ' ' + c.ForeName]++ 
 
    }) 
 
    }) 
 
}) 
 

 
var table = document.body.querySelector('table'); 
 
var thead = '<tr><td></td><td>' + Object.keys(result).join('</td><td>') + '</td></tr>'; 
 
table.innerHTML += thead 
 

 
for (var key in result) { 
 
    var cells = ''; 
 
    for (var i in result[key]) { 
 
    cells += '<td>' + result[key][i] + '</td>'; 
 
    } 
 

 
    var row = '<tr><td>' + key + cells + '</td></tr>'; 
 
    table.innerHTML += row; 
 
}
td:not(:first-child) { 
 
    text-align: center; 
 
}
<table></table>

+0

泰!雖然,我很擔心如何高性能的這將是一個很大的戰鬥。你對緩存結果有什麼看法? Misty和Ash之間的戰鬥與Ash和Misty之間的戰鬥是一樣的。此外,如何在哪裏計數的其他參與者,當一個球員參加我們第一次循環,所以我們只挑選那些戰鬥記錄戰鬥? – SaintPepsi

+0

啊我覺得有一些更有效的解決方案,這確實使用了大量的循環。如果沒有顯示每一個球員每一個球員,但實際上只是誰是相互打架的球員,我認爲這將是簡單得多。 –

+0

請您詳細說明一下這會更簡單嗎? – SaintPepsi

0

隨着2D地圖結構,你可以做到這一點如下:該代碼將返回您在地圖中,每個鍵(玩家名)保持包含姓名和與競爭對手的比賽場次的數量另一個地圖。

function getPlayedMatches(a){ 
 
    return a.reduce(function(r,b){ 
 
        var nl = b.trainers.map(t => t.ForeName + " " + t.LastName); 
 
        return nl.reduce((m,tn) => m.has(tn) ? m.set(tn, nl.reduce((sm,t) => sm.has(t) ? sm.set(t,sm.get(t)+1) 
 
                            : sm.set(t,1), m.get(tn))) 
 
                 : m.set(tn,new Map(nl.map(n => [n,1]))), r); 
 
        }, new Map); 
 
} 
 

 
var matches = [{"battleID":"1","trainers":[{"LastName":"Ketchum","ForeName":"Ash"},{"LastName":"Mason","ForeName":"Misty"}]},{"battleID":"2","trainers":[{"LastName":"Mason","ForeName":"Misty"},{"LastName":"Brock","ForeName":"Stuart"},{"LastName":"Ian","ForeName":"Foster"}]},{"battleID":"3","trainers":[{"LastName":"Brock","ForeName":"Stuart"},{"LastName":"Ketchum","ForeName":"Ash"}]}], 
 
    result = getPlayedMatches(matches); 
 
console.log(function arrayifyMap(m){ 
 
         return m.constructor === Map ? [...m].map(([v,k]) => [arrayifyMap(v),arrayifyMap(k)]) 
 
                : m; 
 
       }(result));