数组对象之间的映射关系

时间:2017-04-08 09:30:43

标签: javascript arrays json algorithm object

鉴于各种口袋妖怪战斗的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"
      }
    ]
  }
]

我想映射一个网格,计算两个Pokemon训练师/玩家之间的匹配数量。一场比赛最多可同时有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

我正在寻找建议,如果我能在vanilla JS /第三方库中做得更好。如何才能使这个效率足以处理大量战斗数据(数百万)。

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分:0)

使用2D地图结构,您可以按如下方式执行此操作;此代码将返回一个地图,其中每个键(播放器的名称)包含另一个地图,其中包含与竞争对手一起玩的名称和匹配数。

&#13;
&#13;
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));
&#13;
&#13;
&#13;