代码之家  ›  专栏  ›  技术社区  ›  xkeshav

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

  •  1
  • xkeshav  · 技术社区  · 6 年前

    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 实现输出的方法。

    感谢您的帮助。

    4 回复  |  直到 6 年前
        1
  •  2
  •   Robert Mennell    6 年前

    所以我将保持数据集不变,但让我们从头开始,创建一些代码来逐步完成数据集并获得所需的输出。

    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(
      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 }))
    

    附加说明

    在这个例子中,我们使用arrow函数来遵循尽可能多地使用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()

    在组合示例中操纵蓄能器。那句话应该说明我们需要做的一切,但对于那些可能不知道的人,我们需要澄清一下, 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}
    
        2
  •  1
  •   amrender singh    6 年前

    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);
        3
  •  1
  •   Ivan Jeffrey Zhao    6 年前

    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);
        4
  •  1
  •   Stuart    6 年前

    另一种方法:按原样循环数据集,将结果存储在 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);
       

    没什么必要 reduce 地图