首页 > 解决方案 > 按键合并数据——减少运行时间

问题描述

我有两个对象数组,我想通过一个键将一个对象数组中的一些数据合并到另一个数组。我有一个涉及嵌套for循环的工作解决方案,但考虑到我的数据,这需要几秒钟。我怎样才能让它更快?我在我的项目中使用 D3 v5。

// Generate data.
let geo = [],
  cases = [];
for (let j = 0; j < 10000; j++) {
  geo.push({
    fips: j,
    name: `foobar ${j}`
  })
  cases.push({
    fips: j,
    time: 0,
    value: Math.floor(Math.random() * 1000)
  })
  cases.push({
    fips: j,
    time: 1,
    value: Math.floor(Math.random() * 1000)
  })
  cases.push({
    fips: j,
    time: 2,
    value: Math.floor(Math.random() * 1000)
  })
}
// Order is not guaranteed.
d3.shuffle(geo);
d3.shuffle(cases);

// Print some example data.
console.log(geo[0]);
console.log(cases[0]);


// Merge some data.
for (let gi = 0; gi < geo.length; gi++) {

  for (let ci = 0; ci < cases.length; ci++) {

    if (geo[gi].fips === cases[ci].fips) {
      let thisTime = cases[ci].time;
      geo[gi][thisTime] = {
        "cases": cases[ci].value
      };
      // Cannot break out of loop early because there can be multiple matching 
      // rows in `cases` for each row in `geo`.
    }
  }
}

// Print example of merged data.
console.log("After loops...")
console.log(geo[0]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

标签: javascriptd3.js

解决方案


您可以将cases数组转换为由fips属性索引的对象,其值是要合并到geo项目中的对象,O(n). 然后遍历geo项目,并Object.assign通过查找fips刚刚构造的对象上的属性来访问它们,也O(n)

// Generate data.
let geo = [],
  cases = [];
for (let j = 0; j < 10000; j++) {
  geo.push({
    fips: j,
    name: `foobar ${j}`
  })
  cases.push({
    fips: j,
    time: 0,
    value: Math.floor(Math.random() * 1000)
  })
  cases.push({
    fips: j,
    time: 1,
    value: Math.floor(Math.random() * 1000)
  })
  cases.push({
    fips: j,
    time: 2,
    value: Math.floor(Math.random() * 1000)
  })
}
// Order is not guaranteed.
d3.shuffle(geo);
d3.shuffle(cases);

// Merge some data.
const caseValueObjsByFips = {};
for (const aCase of cases) {
  if (!caseValueObjsByFips[aCase.fips]) caseValueObjsByFips[aCase.fips] = {};
  caseValueObjsByFips[aCase.fips][aCase.time] = { cases: aCase.value };
}
for (const item of geo) {
  Object.assign(item, caseValueObjsByFips[item.fips]);
}
// Print example of merged data.
console.log("After loops...")
console.log(geo[0]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>


推荐阅读