6

Please see this example: JsFiddle

Question: I have the following JSON Array

y= [ {"LngTrend":15,"DblValue":10,"DtmStamp":1358226000000},     
{"LngTrend":16,"DblValue":92,"DtmStamp":1358226000000},    
{"LngTrend":17,"DblValue":45,"DtmStamp":1358226000000},
{"LngTrend":18,"DblValue":87,"DtmStamp":1358226000000},


{"LngTrend":15,"DblValue":10,"DtmStamp":1358226060000},
{"LngTrend":16,"DblValue":87,"DtmStamp":1358226060000},
{"LngTrend":17,"DblValue":45,"DtmStamp":1358226060000},
{"LngTrend":18,"DblValue":92,"DtmStamp":1358226060000} ]

I was trying to group these object by DtmStamp end up having something like this :

 x =  [[1358226000000,10,92,45,87],[1358226060000,10,87,45,92], .......]

In other words:

x[0][0] = y[0].DtmStamp ;
x[0][1] = y[0].LngTrend ;
x[0][2] = y[1].LngTrend ;
x[0][3] = y[2].LngTrend ; 
x[0][4] = y[3].LngTrend ;

Unfortunately, it ends with something I don't want.

Here is what I have tried so far:

   var dataTrendArray = [];
           $.each(x, function (index, value) {
                var trendArray = [];
                if (index % 4 == 0) {
                    trendArray.push(x[index].DtmStamp);
                    for (var i = 0; i < 4; i++) {
                        index = eval(index + i);
                        trendArray.push(x[index].DblValue);
                    }
                }

               console.log(trendArray) ;
                dataTrendArray.push(trendArray);
            });

Can someone help me get on the right path?

1
  • 1
    Don't mix $.each with for-loops. And don't use eval Commented Jan 29, 2013 at 22:24

5 Answers 5

17

You can leverage JavaScript objects as a key/value data structure similar to a map. The property name will serve as the key, while the property value will serve as the value. This will allow you to group.

var y = [
     {"LngTrend":15,"DblValue":10,"DtmStamp":1358226000000},     
     {"LngTrend":16,"DblValue":92,"DtmStamp":1358226000000},    
     {"LngTrend":17,"DblValue":45,"DtmStamp":1358226000000},
     {"LngTrend":18,"DblValue":87,"DtmStamp":1358226000000},
     {"LngTrend":15,"DblValue":10,"DtmStamp":1358226060000},
     {"LngTrend":16,"DblValue":87,"DtmStamp":1358226060000},
     {"LngTrend":17,"DblValue":45,"DtmStamp":1358226060000},
     {"LngTrend":18,"DblValue":92,"DtmStamp":1358226060000},
];

var x = {};

for (var i = 0; i < y.length; ++i) {
    var obj = y[i];

    //If a property for this DtmStamp does not exist yet, create
    if (x[obj.DtmStamp] === undefined)
        x[obj.DtmStamp] = [obj.DtmStamp]; //Assign a new array with the first element of DtmStamp.

    //x will always be the array corresponding to the current DtmStamp. Push a value the current value to it.
    x[obj.DtmStamp].push(obj.DblValue);
}

console.log(x); //x is now an object grouped by DtmStamp. You can easily turn it back into an array here.
Sign up to request clarification or add additional context in comments.

Comments

8

You should use a hash. A hash will allow you to easily index all of the DblValue values by DtmStamp. Here is a full working example:

jsFiddle

var y = [ {"LngTrend":15,"DblValue":10,"DtmStamp":1358226000000},     
{"LngTrend":16,"DblValue":92,"DtmStamp":1358226000000},    
{"LngTrend":17,"DblValue":45,"DtmStamp":1358226000000},
{"LngTrend":18,"DblValue":87,"DtmStamp":1358226000000},
{"LngTrend":15,"DblValue":10,"DtmStamp":1358226060000},
{"LngTrend":16,"DblValue":87,"DtmStamp":1358226060000},
{"LngTrend":17,"DblValue":45,"DtmStamp":1358226060000},
{"LngTrend":18,"DblValue":92,"DtmStamp":1358226060000} ];

var x = {};

var i = 0;
while(i++ < y.length) {
    var key = y[i].DtmStamp.toString();
    if (typeof(x[key]) == "undefined") x[key] = [];
    x[key].push(y[i].DblValue);
}

alert(JSON.stringify(x));

The key is to use a hash on the values you want to group by.

Result:

{
    "1358226060000": [
        92,
        45,
        87,
        10
    ],
    "1358226000000": [
        87,
        45,
        92,
        10
    ]
}

If you want to prevent duplicates, you can do so by adding if/then logic in conjunction with indexOf().

7 Comments

While it is conceptually right to use an object, that linked article contains a few bad practises. Also, your code is a bit weird sometimes (backward iteration, explicit string conversion...)
while(i--){} is a common thing to do. Nicholas Zakas promotes its use as the most efficient loop in JavaScript. Regarding the string conversion, I prefer explicit conversions--easier for others to follow imho.
Not sure why anyone would care about those few saved microseconds, but the greater disadvantage is that it reverses the order and so does not match the OPs expected output.
It's faster to type and faster to execute. Often times the order of the data doesn't matter. If it does, then the OP can go back to use $.each or a normal i++ loop.
looks good but ..why does the values are not in the proper order the first object should be [10,92,45,87] not [92,45,87,10] Thanks
|
0

Your code pushes empty trendArrays even if they are not filled (index % 4 != 0). Instead, use this:

var dataTrendArray = [];
for (var i = 0; i < x.length; i += 4) {
    var trendArray = [ x[i].DtmStamp ];
    for (var j = i, l = Math.max(i + 4, x.length); j < l; j++) {
        trendArray.push(x[j].DblValue);
    }
    // console.log(trendArray) ;
     dataTrendArray.push(trendArray);
}

However, it might fit better if you just grouped the trendArrays into an object, using the DtmStamp as keys:

var dataTrend = {};
for (var i=0; i<x.length; i++) {
    var key = x[i].DtmStamp;
    if (key in dataTrend)
        dataTrend[key].push(x[i].DblValue);
    else
        dataTrend[key] = [ x[i].DblValue ];
}

Comments

0

You can build a sparse array, indexed by DtmStamp.

var x = [];
$.each(y, function(i, obj) {
    var s = obj.DtmStamp;
    if(!x[s]) x[s] = [];
    x[s].push(obj.DblValue);
});

//x is now a sparse array, indexed by DtmStamp

This has the advantage over an object, that the array elements are in DtmStamp order.

//To loop through x
for(i in x) {
    ...
}

8 Comments

With for in, the order is not guaranteed even for arrays.
@Bergi, you may well be correct but I ran some (admittedly limited) tests which demonstrated that for(i in x) looped through in order. Do you know the conditions under which the order will fail?
No, I haven't seen any browser in the wild that does not order numeric keys (because there's too much bad code expecting it). Still I cannot recommend it.
My understanding is that a bigger issue with for(prop in Array) is that irrelevant properties may be found. A general solution is provided here, though in the example above, a much simpler test would suffice, eg if($.isArray(x[i]){...}).
Yes, I guess that is the real issue.
|
0
 var y = [
   {"LngTrend":15,"DblValue":10,"DtmStamp":1358226000000},     
   {"LngTrend":16,"DblValue":92,"DtmStamp":1358226000000},    
   {"LngTrend":17,"DblValue":45,"DtmStamp":1358226000000},
   {"LngTrend":18,"DblValue":87,"DtmStamp":1358226000000},
   {"LngTrend":15,"DblValue":10,"DtmStamp":1358226060000},
   {"LngTrend":16,"DblValue":87,"DtmStamp":1358226060000},
   {"LngTrend":17,"DblValue":45,"DtmStamp":1358226060000},
   {"LngTrend":18,"DblValue":92,"DtmStamp":1358226060000},
 ];
var x = {};

for(var k in y){
  if(x[y[k]["DtmStamp"]] == undefined)
     x[y[k]["DtmStamp"]] = [];
     x[y[k]["DtmStamp"]].push(y[k]["DblValue"])
}
alert(JSON.stringify(x))
console.log(x);

See http://plnkr.co/edit/511sKSdzHGYuvpYqKCPD?p=preview

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.