Javascript基于多个级别以平面格式创建数组

时间:2018-03-14 18:31:59

标签: javascript arrays highcharts

我正在尝试创建一个堆叠条形图,如下例所示:http://jsfiddle.net/fct1p8j8/4/

在对数据进行硬编码时,它自己运行的图表很好,一切都很好。

我正在努力弄清楚如何从我的数据库结构中获取正确格式的数据。

以下是我的数据设置的示例输出:

[
  {
    "invDept": "Due Diligence",
    "programs": {
      "data": [
        {
          "program": "Brand Risk Management",
          "total": "1847"
        },
        {
          "program": "Due Diligence",
          "total": "2718"
        },
        {
          "program": "SAR",
          "total": "17858"
        }
      ]
    }
  },
  {
    "invDept": "Sanctions",
    "programs": {
      "data": [
        {
          "program": "Brand Risk Management",
          "total": "500"
        },
        {
          "program": "Due Diligence",
          "total": "2100"
        },
        {
          "program": "SAR",
          "total": "16593"
        }
      ]
    }
  }
]

x轴将是来自对象的invDepartment值。 系列数据是我需要制作图表所需的格式。

对于每个部门,我需要数组格式的每个程序的值。

例如,Brand Risk Management是程序名称,我需要来自Due Diligence部门和Sanctions部门的值。

我开始做一个基本循环来创建数组结构,如下所示:

//获取X轴的部门

$.each(data.data, function (key, value) {

    d = value;

    xAxis.push(value.invDept);

    // If an array for the department doesn't exist, create it now
    if (typeof res[d.invDept] == "undefined" || !(res[d.invDept] instanceof Array)) {
        res[d.invDept] = [];
    }

});

从这里我有类似的东西:

res['Due Diligence'] = []

我在这一点上陷入困​​境。我不太确定如何设置循环以获得平面格式的数据。

最终输出如下:

series: [{
    name: 'Brand Risk Management',
    data: [1847, 500]
}, {
    name: 'Due Diligence',
    data: [2718, 2100]
}, {
    name: 'SAR',
    data: [17858, 16593]
}]

4 个答案:

答案 0 :(得分:1)

使用Array.concat()Array.map()spread syntax将数据展平为单个数组。

然后reduces数组到Map,它将具有相同键的对象合并到所需的结果中。完成后,使用Map.values()和扩展语法将Map转换回数组。

const data = [{"invDept":"Due Diligence","programs":{"data":[{"program":"Brand Risk Management","total":"1847"},{"program":"Due Diligence","total":"2718"},{"program":"SAR","total":"17858"},{"program":"Sanctions - WLM","total":"885"}]}},{"invDept":"Sanctions","programs":{"data":[{"program":"Brand Risk Management","total":"500"},{"program":"Due Diligence","total":"2100"},{"program":"SAR","total":"16593"},{"program":"Sanctions - WLM","total":"443"}]}}]

const result = [... // spread the iterator to a new array
  // flatten the array
  [].concat(...data.map(({ programs }) => programs.data))
  // reduce the data into a map
  .reduce((r, { program: name, total }) => {
      // if key doesn't exist create the object
      r.has(name) || r.set(name, { name, data: [] }) 
      // get the object, and add the total to the data array
      r.get(name).data.push(total) 

      return r;
    }, new Map())
  .values()] // get the Map's values iterator
  
console.log(result)

答案 1 :(得分:1)

您可以使用reduce功能。

var array = [  {    "invDept": "Due Diligence",    "programs": {      "data": [        {          "program": "Brand Risk Management",          "total": "1847"        },        {          "program": "Due Diligence",          "total": "2718"        },        {          "program": "SAR",          "total": "17858"        }      ]    }  },  {    "invDept": "Sanctions",    "programs": {      "data": [        {          "program": "Brand Risk Management",          "total": "500"        },        {          "program": "Due Diligence",          "total": "2100"        },        {          "program": "SAR",          "total": "16593"        }      ]    }  }],
    result = { series: Object.values(array.reduce((a, c) => {
      c.programs.data.forEach((d) => 
        (a[d.program] || (a[d.program] = {data: [], name: d.program})).data.push(d.total));
      return a;
}, {}))};

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:0)

您可以使用array#reduce遍历数组并将值存储在对象累加器中。使用programs迭代data array#forEach并填充对象累加器。然后使用Object.values()

提取所有值

var data = [ { "invDept": "Due Diligence", "programs": { "data": [ { "program": "Brand Risk Management", "total": "1847" }, { "program": "Due Diligence", "total": "2718" }, { "program": "SAR", "total": "17858" }, { "program": "Sanctions - WLM", "total": "885" }] } }, { "invDept": "Sanctions", "programs": { "data": [ { "program": "Brand Risk Management", "total": "500" }, { "program": "Due Diligence", "total": "2100" }, { "program": "SAR", "total": "16593" }, { "program": "Sanctions - WLM", "total": "443" }] } } ],
    result = Object.values(data.reduce((r,o) => {
      o.programs.data.forEach(({program, total}) => {
        r[program] = r[program] || {name: program, data: []};
        r[program].data.push(total);
      });
      return r;
    },{})),
    output = {series: result};
console.log(output);
.as-console-wrapper{ max-height: 100% !important; top: 0;}

答案 3 :(得分:0)

您可以使用reduce方法并将每个程序存储在新对象中作为其数组的键。我不知道你是否想要重复,但如果没有,你只需将array object替换为set object而将push替换为add

let myPrograms = data.reduce((accumulator, item) => {
item && item.programs && item.programs.data && accumulateData(item.programs.data);

function accumulateData(program_data) {
  for (let item of program_data) {
    accumulator[item.program] ||
      (accumulator[item.program] = [item.total],
        accumulator[item.program].push(item.total));
  }
}
return accumulator;
}, {});

您可以像这样访问myPrograms内的数据数组:

myPrograms["name of program"];

let data = [{
    "invDept": "Due Diligence",
    "programs": {
      "data": [{
          "program": "Brand Risk Management",
          "total": "1847"
        },
        {
          "program": "Due Diligence",
          "total": "2718"
        },
        {
          "program": "SAR",
          "total": "17858"
        },
        {
          "program": "Sanctions - WLM",
          "total": "885"
        }
      ]
    }
  },
  {
    "invDept": "Sanctions",
    "programs": {
      "data": [{
          "program": "Brand Risk Management",
          "total": "500"
        },
        {
          "program": "Due Diligence",
          "total": "2100"
        },
        {
          "program": "SAR",
          "total": "16593"
        },
        {
          "program": "Sanctions - WLM",
          "total": "443"
        }
      ]
    }
  }
];

let myPrograms = data.reduce((accumulator, item) => {
  item&&item.programs&&item.programs.data&& 
  accumulateData(item.programs.data);

  function accumulateData(program_data) {
    for (let item of program_data) {
      accumulator[item.program] || (accumulator[item.program] = [item.total], accumulator[item.program].push(item.total));
    }
  } 
  return accumulator;
}, {});

console.log(myPrograms);
console.log(myPrograms["Brand Risk Management"]);