1

I've got an array of objects:

 var arr = [
    {
        timemark: "2017-03-01",
        db_total: c1,
        db_used: d1,
        hosts: e1,
        items: f1
    },{
        timemark: "2017-03-02",
        db_total: c2,
        db_used: d2,
        hosts: e2,
        items: f2
    },{
        timemark: "2017-03-03",
        db_total: c3,
        db_used: d3,
        hosts: e3,
        items: f3
    },..]

I am struglling how to transform it to another array but with different structure:

var result = [
    {
        topic: "db_total",
        data: [
            {
                x: "2017-03-01",
                y: c1
            },{
                x: "2017-03-02",
                y: c2
            },{
                x: "2017-03-03",
                y: c3
            },...]
    },{
        topic: "db_used",
        data: [
            {
                x: "2017-03-01",
                y: d1
            },{
                x: "2017-03-02",
                y: d2
            },{
                x: "2017-03-03",
                y: d3
            },...]
    },{
        topic: "hosts",
        data: [
            {
                x: "2017-03-01",
                y: e1
            },{
                x: "2017-03-02",
                y: e2
            },{
                x: "2017-03-03",
                y: e3
            },...]
    },{
        topic: "items",
        data: [
            {
                x: "2017-03-01",
                y: f1
            },{
                x: "2017-03-02",
                y: f2
            },{
                x: "2017-03-03",
                y: f3
            },...]
    },...];

I know I have to do something like this:

//convert
var result = [];
for (var i=0; i<arr.length; i++) {
  result[i]=[arr[i].timemark];
}

Which creates array of arrays:

[
    [2017-03-01],
    [2017-03-02],
    [2017-03-03]
]

It is kinda a start after some hours. But I can't find a way how to start creating objects inside the array instead of arrays? Trying to go baby steps :)

but I am really having problems understanding the snippet and probably using wrong syntax can't get it to work.

Could someone explain how to properly use loop in this case?

0

5 Answers 5

2

You can do such a logic; mapping for each grouping, and compiling the final result object;

var arr = [
    {
        timemark: "2017-03-01",
        db_total: "c1",
        db_used: "d1",
        hosts: "e1",
        items: "f1"
    },{
        timemark: "2017-03-02",
        db_total: "c2",
        db_used: "d2",
        hosts: "e2",
        items: "f2"
    },{
        timemark: "2017-03-03",
        db_total: "c3",
        db_used: "d3",
        hosts: "e3",
        items: "f3"
    }];

var result = [];
Object.keys(arr[0])
      .filter(field => field != "timemark")
      .forEach(field => result.push(finalObj(field, arr.map(e => xy(e.timemark, e[field])))));

console.log(result);

function xy(x, y) {
     return { x : x, y : y };
}

function finalObj(name, arr) {
     return { topic : name, data : arr };
}

Since you were suggesting you'd have more fields, thus more topics in the final object, if that is the case, I have modified so that the more fields you add, it will automatically show up in the final resulting object. (Except timemark field ofc)

Sign up to request clarification or add additional context in comments.

7 Comments

That's great!!! Could you explain where you use function xy()? I basically kinda understand everything else :)
it is inside the mapping of arr, just didn't want to use such hardcoding in the algorithm part :) But you can move them there to make it a one liner if you'd like
The only issue I see is that you're not guarding against inherited enumerable properties of the objects. Something like Object.keys(arr[0]).reduce(..., []) would fix that and create the result array in one go. Otherwise, very elegant.
@RobG, do you mean while doing a forEach of the objects fields, some inherited fields etc might pop up? Does using Object.keys(obj) evade that issue?
No, for..in is the issue. It iterates over all enumerable properties, including inherited ones. Object.keys gets just own properties (and is a bit simpler than a hasOwnProperty check).
|
1

You can use reduce to do that

var arr = [{timemark: "2017-03-01",db_total: 'c1',db_used: 'd1',hosts: 'e1',items: 'f1'}, {timemark: "2017-03-02",db_total: 'c2',db_used: 'd2',hosts: 'e2',items: 'f2'}, {timemark: "2017-03-03",db_total: 'c3',db_used: 'd3',hosts: 'e3',items: 'f3'}];

let res = arr.reduce((a, b) => {
    for (let key in b) {
        if (b.hasOwnProperty(key) && key !== 'timemark' && ! a.find(v => v.topic === key)) {
            a.push({
                topic: key,
                data: arr.map(o => ({
                    x: o.timemark,
                    y: o[key]
                }))
            });
        }
    }
    return a;
}, []);

console.log(res);

Just for the fun of playing with Maps - below would give another resultset as you intended, but dependending on the further use of your data, it might be helpful (and the code for the creation is also much shorter):

var arr = [{timemark: "2017-03-01",db_total: 'c1',db_used: 'd1',hosts: 'e1',items: 'f1'}, {timemark: "2017-03-02",db_total: 'c2',db_used: 'd2',hosts: 'e2',items: 'f2'}, {timemark: "2017-03-03",db_total: 'c3',db_used: 'd3',hosts: 'e3',items: 'f3'}];

let r = arr.reduce((a,b) => {
    for (let key in b) {
        if (b.hasOwnProperty(key) && key !== 'timemark')
            a.set(key, (a.get(key) || [] ).concat({x: b.timemark, y: b[key]}))
    }
    return a;
}, new Map());

console.log(r);

// USAGE 

// get the data array for db_total:
console.log(r.get("db_total"));

// or for hosts:
console.log(r.get("hosts"));

Comments

1

You can use the Array.prototype's map function to map each element from the array to a different one, conserving the length of the array.

ex:

var result = arr.map(e => ({x: e.timemark, y:db_total}));

var input = [{
        timemark: "2017-03-01",
        db_total: 1,
        db_used: 1,
        hosts: 1,
        items: 1
    },{
        timemark: "2017-03-02",
        db_total: 1,
        db_used: 1,
        hosts: 1,
        items: 1
    },{
        timemark: "2017-03-03",
        db_total: 1,
        db_used: 1,
        hosts: 1,
        items: 1
    }];
var output = [{
  topic:'db_total',
  data: input.map(e=> ({x:e.timemark, y:e.db_total}))
},{
  topic:'db_used',
  data: input.map(e=> ({x:e.timemark, y:e.db_used}))
},{
  topic:'hosts',
  data: input.map(e=> ({x:e.timemark, y:e.hosts}))
},{
  topic:'items',
  data: input.map(e=> ({x:e.timemark, y:e.items}))
}]
console.log(output)

1 Comment

Just noticed I'm wrong about what you ment, sec editing my answer.
1

var arr = [{
    timemark: "2017-03-01",
    db_total: 'c1',
    db_used: 'd1',
    hosts: 'e1',
    items: 'f1'
},{
    timemark: "2017-03-02",
    db_total: 'c2',
    db_used: 'd2',
    hosts: 'e2',
    items: 'f2'
},{
    timemark: "2017-03-03",
    db_total: 'c3',
    db_used: 'd3',
    hosts: 'e3',
    items: 'f3'
}];

console.log(_getConvertedArray(arr))

function _getConvertedArray(array){
    var res = [];
    array.forEach(function(obj){
        Object.keys(obj).forEach(function(key){
            res.push({
                topic: key,
                data: _getTopicData(arr, key)
            });
        });
    });

    return res;
}

function _getTopicData(array, topic){
    var res = [];

    array.forEach(function(obj){
        res.push({
            x: obj.timemark,
            y: obj[topic]
        });
    });

    return res;
}

1 Comment

Why use a fiddle? Just post it as a runnable snippet here.
0

As a fairly simple but very specific function, you can create an "empty" result array and fill it in:

var arr = [
    {
        timemark: "2017-03-01",
        db_total: 'c1',
        db_used: 'd1',
        hosts: 'e1',
        items: 'f1'
    },{
        timemark: "2017-03-02",
        db_total: 'c2',
        db_used: 'd2',
        hosts: 'e2',
        items: 'f2'
    },{
        timemark: "2017-03-03",
        db_total: 'c3',
        db_used: 'd3',
        hosts: 'e3',
        items: 'f3'
    }
];


var result = [{topic: "db_total",data: []},
              {topic: "db_used",data: []},
              {topic: "hosts",data: []},
              {topic: "items",data: []}
             ];

arr.forEach(function (obj) {
  result[0].data.push({x:obj.timemark,y: obj.db_total});
  result[1].data.push({x:obj.timemark,y: obj.db_used});
  result[2].data.push({x:obj.timemark,y: obj.hosts});
  result[3].data.push({x:obj.timemark,y: obj.items});
});

console.log(result);

Or you could go for a more general approach that only depends on the timemark property and builds a result from whatever other properties are provided:

var arr = [{
  timemark: "2017-03-01",
  db_total: 'c1',
  db_used: 'd1',
  hosts: 'e1',
  items: 'f1'
}, {
  timemark: "2017-03-02",
  db_total: 'c2',
  db_used: 'd2',
  hosts: 'e2',
  items: 'f2'
}, {
  timemark: "2017-03-03",
  db_total: 'c3',
  db_used: 'd3',
  hosts: 'e3',
  items: 'f3'
}]

// Collect keys but exclude timemark
var keys = Object.keys(arr[0]).filter(function(v) {
  return v != 'timemark';
});

// Build result: loop over every object in arr
var result = arr.reduce(function(result, obj) {
  // Build object to insert into result array
  Object.keys(obj).forEach(function(p) {
    var i = keys.indexOf(p);
    // Create object for key if it's not timemark and doesn't exist
    // And push the data
    if (i != -1) {
      result[i] = result[i] || {topic:p, data:[]};
      result[i].data.push({x:obj.timemark,y:obj[p]});
    }
  })
  return result;
}, []);

console.log(result);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.