如何使用ES6数组方法将多维数组转换为图表数据

时间:2018-06-25 17:30:56

标签: javascript arrays ecmascript-6

我需要将一个数组转换为特定的数据格式以显示图表。

chrat.js库要求此格式的数据

dataset = [ { label: 'one', data: []}, 
           {label: 'two', data: []}
        ];

我会以随机顺序接收另一种格式的响应数据,因此需要使用相应的标签进行适当的更改。

这是我的代码和试用版。

const dataset = [
    {
        detail: {
            team: [
                { name: 'alpha', game: 1 },
                { name: 'beta', game: 1 },
                { name: 'gamma', game: 1 },
                { name: 'delta', game: 1 },
                { name: 'echo', game: 1 }
            ]
        }
    },
    {
        detail: {
            team: [
                { name: 'alpha', game: 2 },
                { name: 'beta', game: 2 },
                { name: 'echo', game: 2 },
                { name: 'gamma', game: 2 },
                { name: 'delta', game: 2 }
            ]
        }
    },
    {
        detail: {
            team: [
                { name: 'echo', game: 1 },
                { name: 'delta', game: 0 },
                { name: 'beta', game: 0 },
                { name: 'gamma', game: 0 },
                { name: 'alpha', game: 0 }
            ]
        }
    },
    {
        detail: {
            team: [
                { name: 'delta', game: 0 },
                { name: 'echo', game: 0 },
                { name: 'beta', game: 0 },
                { name: 'gamma', game: 1 },
                { name: 'alpha', game: 0 }
            ]
        }
    },
    {
        detail: {
            team: [
                { name: 'delta', game: 0 },
                { name: 'echo', game: 0 },
                { name: 'alpha', game: 2 },
                { name: 'gamma', game: 3 },
                { name: 'beta', game: 2 }
            ]
        }
    },
    {
        detail: {
            team: [
                { name: 'delta', game: 0 },
                { name: 'echo', game: 1 },
                { name: 'beta', game: 0 },
                { name: 'gamma', game: 2 },
                { name: 'alpha', game: 0 }
            ]
        }
    }
];


const teams = dataset.map(ds => ds.detail.team);
let z = teams.map(element => {
    return element.map(e => {
        let p = {};
        let n = e.name;
        let c = e.game;
        p[n] = c;
        return p;
    });
});

console.log('z', z);

let nt = [];

z.reduce((c, n, i, a) => {
    let z1 = n.map((i) => {
        console.log(i);
        let entries = Object.entries(i);
        return entries.map((e) => {
          return { label: e[0], data: e[1] };
        });
    });
    return z1;
}, [])
  

所需的输出:

[
    {
        label: 'alpha',
        data: [1, 2, 0, 0, 2, 0]
    },
    {
        label: 'beta',
        data: [1, 2, 0, 0, 2, 0]
    },
    {
        label: 'gamma',
        data: [1, 2, 0, 1, 3, 2]
    },
    {
        label: 'delta',
        data: [ 1, 2, 0, 0, 0, 0]
    },
    {
        label: 'echo',
        data: [1, 2, 1, 0, 0, 1]
    }
]

我在array.reduce方法的某个地方迷失了方向,以实现输出。

我最好在寻找es6解决方案

感谢您的帮助。

4 个答案:

答案 0 :(得分:2)

因此,我将保留您的数据集不变,但让我们从头开始,创建一些代码以逐步遍历数据集并获得所需的输出。

首先,我们需要对数据进行嵌套:

dataset.map(d => d.detail.team)

现在我们有了团队,可以将它们全部缩减为一个阵列

dataset
  .map(object => object.detail.team)
  .reduce((acc, team) => acc.concat(team))

好的,现在我们有了一大套名称和游戏。我们现在可以很容易地将其变成哈希

dataset
  .map(object => object.detail.team)
  .reduce((acc, team) => acc.concat(team))
  .reduce((acc, team) =>{
    acc[team.name] = acc[team.name] || []
    acc[team.name].push(team.game)
    return acc
  }, {})

现在,我们为游戏添加了一个名称哈希。在此哈希上调用Object.entries将为我们提供一对标签

Object.entries(
  dataset
    .map(object => object.detail.team)
    .reduce((acc, team) => acc.concat(team))
    .reduce((acc, team) =>{
      acc[team.name] = acc[team.name] || []
      acc[team.name].push(team.game)
      return acc
    }, {})
)

现在我们可以映射这些对以构造最终对象

Object.entries(
  dataset
    .map(object => object.detail.team)
    .reduce((acc, team) => acc.concat(team), [])
    .reduce((acc, team) =>{
      acc[team.name] = acc[team.name] || []
      acc[team.name].push(team.game)
      return acc
    }, {})
)
  .map(([team, games]) => ({ team, games }))

现在真正的窍门是可以将这些步骤中的多少合并?

其中大多数!我们可以将其简化为遍历每个对象,由于我们知道结构,因此可以手动进行引用,然后遍历每个单独的团队数组并最终构造我们的哈希。

Object.entries(
  dataset
    .reduce((acc, object) =>{
      object.detail.team.forEach(team =>{
        acc[team.name] = acc[team.name] || []
        acc[team.name].push(team.game)
      })
      return acc
    }, {})
)
  .map(([team, games]) => ({ team, games }))

额外说明

箭头功能

在本示例中,我们使用了箭头功能来尽可能地遵循使用ES6的要求。 More information on arrow functions can be found on the MDN.基本上是声明函数的另一种方式

function test(value){ return console.log(value) }
// same as
let test = value => console.log(value)

function add(a, b){ return a + b)
// same as
let add = (a,b) => a + b

注意Array.prototype.forEach()

现在您会注意到我们在组合示例中使用了Array.prototype.forEach()来操纵累加器。该语句应该说出我们需要的所有内容,但为了澄清可能不了解的人,如果您不希望返回任何值而只想要副作用,那么可以使用forEach。在这种情况下,它比尝试实际返回内容要快,因为我们不希望在最终目标只是更改累加器的外观时放弃丢弃我们制作的一堆数组的开销。

那个时髦的数组被传递给函数

是的,破坏性。 Again more information can be found on the MDN.基本上,它使我们可以从预先知道结构的对象或数组中提取值。注意:示例由MDN文章提供

var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20


// Stage 3 proposal
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c: 30, d: 40}

答案 1 :(得分:1)

您可以使用Array.reduce()创建地图,然后使用该地图获取所需的输出。

const dataset = [{detail:{team:[{name:'alpha',game:1},{name:'beta',game:1},{name:'gamma',game:1},{name:'delta',game:1},{name:'echo',game:1}]}},{detail:{team:[{name:'alpha',game:2},{name:'beta',game:2},{name:'echo',game:2},{name:'gamma',game:2},{name:'delta',game:2}]}},{detail:{team:[{name:'echo',game:1},{name:'delta',game:0},{name:'beta',game:0},{name:'gamma',game:0},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'beta',game:0},{name:'gamma',game:1},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'alpha',game:2},{name:'gamma',game:3},{name:'beta',game:2}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:1},{name:'beta',game:0},{name:'gamma',game:2},{name:'alpha',game:0}]}}];
var map = dataset.reduce((a,curr)=>{
    curr.detail.team.forEach((e)=> (a[e.name]= (a[e.name] || [])).push(e.game));
    return a;
}, {});
var result =[];

Object.keys(map).forEach((key)=>{
  result.push({
    "label" : key,
    "data" : map[key]
  });
});

console.log(result);

答案 2 :(得分:1)

您可以使用reduce制作平面数组,然后循环获取所需的格式

const dataset = [{detail:{team:[{name:'alpha',game:1},{name:'beta',game:1},{name:'gamma',game:1},{name:'delta',game:1},{name:'echo',game:1}]}},{detail:{team:[{name:'alpha',game:2},{name:'beta',game:2},{name:'echo',game:2},{name:'gamma',game:2},{name:'delta',game:2}]}},{detail:{team:[{name:'echo',game:1},{name:'delta',game:0},{name:'beta',game:0},{name:'gamma',game:0},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'beta',game:0},{name:'gamma',game:1},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'alpha',game:2},{name:'gamma',game:3},{name:'beta',game:2}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:1},{name:'beta',game:0},{name:'gamma',game:2},{name:'alpha',game:0}]}}];
const flat = dataset.reduce( (a,b) => a.concat(b.detail.team), []);
let result = [];

for (let element of flat) {

  let match = null;

  for (let e  of result) {
    if (e.label === element.name) {
      match = e;
    }
  }

  if (match) {
    match.data.push(element.game)
  }
  else {
    result.push({
      label : element.name,
      data  : [element.game]
    });
  }

}

console.log(result);

答案 3 :(得分:1)

另一种方法:按原样循环访问数据集,将结果存储在类似字典的map字典对象中,并存储在要返回的结果数组中。

const dataset = [{detail:{team:[{name:'alpha',game:1},{name:'beta',game:1},{name:'gamma',game:1},{name:'delta',game:1},{name:'echo',game:1}]}},{detail:{team:[{name:'alpha',game:2},{name:'beta',game:2},{name:'echo',game:2},{name:'gamma',game:2},{name:'delta',game:2}]}},{detail:{team:[{name:'echo',game:1},{name:'delta',game:0},{name:'beta',game:0},{name:'gamma',game:0},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'beta',game:0},{name:'gamma',game:1},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'alpha',game:2},{name:'gamma',game:3},{name:'beta',game:2}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:1},{name:'beta',game:0},{name:'gamma',game:2},{name:'alpha',game:0}]}}];
var result = [],
  map = {};
dataset.forEach(a => {
  a.detail.team.forEach(b => {
    if (!(b.name in map)) {
      map[b.name] = [];
      result.push({
        'label': b.name,
        'data': map[b.name]
      })
    }
    map[b.name].push(b.game);
  });
});
console.log(result);
   

这里不需要reducemap任何数组。