1

I have two js arrays already, say: names and values (with the same length), now I would like to construct a json object in certain format? For example:

 names = ["label1","label2","label3"];
 values = [[[0,1],[1,9],[2,10]],[[0,89],[1,91],[2,1]],[[0,1],[1,9],[2,10]]];

I would like to have a json array data_spec in this format:

 [{
    label:"label1",
    data:[[0,1],[1,9],[2,10]]
  },
  {
    label:"label2",
    data:[[0,89],[1,91],[2,1]]
  },
  {
    label:"label3",
    data:[[0,1],[1,9],[2,10]]
  }]

Could anyone tell one how? Thanks a lot!

WilliamLou
  • 1,914
  • 6
  • 27
  • 38

3 Answers3

6

For a bit of variety and a check,

var data_spec = [];
if (names.length != values.length) {
    // panic, throw an exception, log an error or just return an empty array
} else {
    for (var i=0, name; name = names[i]; i++) { // assuming a non-sparse array
        data_spec[i] = { 
            label : name, 
            data  : values[i] 
        };
    }
}

That is, non-sparse and not containing anything else that would evaluate to false.

If your framework has an each function added to Array and you don't care about performance,

var data_spec = [];
names.each(function(name) {
    data_spec.push({ label : name, data : values[names.indexOf(name)] });
});

If your framework is a clean one like Dojo and puts it somewhere else (ex is Dojo),

var data_spec = [];
dojo.forEach(names, function(name) {
    data_spec.push({ label : name, data : values[names.indexOf(name)] });
});

If your framework has an each function that returns an Array of identical length with the results of every operation at their expected position,

var data_spec = arrayOfResultsEach(names, function(name) {
    return { label : name, data : values[names.indexOf(name)] };
});

These are just for illustration, indexOf inside loops of arbitrary length is a major code smell.

Michiel Kalkman
  • 3,054
  • 24
  • 25
  • 1
    Most array iterator implementations (prototype, jQuery.each) also pass the `index` parameter to the iterator function. So you don't need the `indexOf`. – Chetan S Dec 11 '09 at 20:34
2

Just use a loop (make sure the two arrays are of same length)

result = [];
for(var i=0, len=names.length; i < len; i++) {
    result.push({label: names[i], data: values[i]});
}
Chetan S
  • 23,637
  • 2
  • 63
  • 78
  • @Chetan, please optimize your for loop by calculating **names.length** outside of the loop and I'll give you +1 – Corey Ballou Dec 10 '09 at 00:24
  • Done, but is Array#length expensive enough to bother? I know nodelist#length is. – Chetan S Dec 10 '09 at 00:27
  • I can't say for sure which is more costly, but the optimization alone reduces the calls to **names.length** by N where N is the number of array items (which *could* be very costly) – Corey Ballou Dec 10 '09 at 00:35
  • I prefer something like `for (var i=0; names[i]; i++) {}` for situations like this, when you know names[i] would never be 0, false, null, undefined or a blank string :-) – Andy E Dec 10 '09 at 00:40
  • array.length isn't a call it's a property of the object. there's no optimization to be found changing this code .. http://stackoverflow.com/questions/1208320/what-is-the-cost-of-calling-array-length – Scott Evernden Dec 10 '09 at 03:19
  • @Scott: I ran a few benchmarks and only IE seemed to run marginally slower (about 4%) when array.length was accessed repeatedly. Now the linked question is for java which is JIT'ed and is not a dynamic language. But in this case, I do agree that it's rather a premature optimization and is not worth the cost of reduced readability. – Chetan S Dec 11 '09 at 20:31
-2
    var myArray = 
    [{
        "label": "label1",
        "data" : 
        {
            "0": "1",
            "1": "9",
            "2": "10"
        }
    },

    {
        "label": "label2",
        "data" : 
        {
            "0": "89",
            "1": "91",
            "2": "1"
        }
    },

    {
        "label": "label3",
        "data" : 
        {
            "0": "1",
            "1": "9",
            "2": "10"
        }
    }];

    alert(myArray[0].data[2]);
AmbrosiaDevelopments
  • 2,576
  • 21
  • 28
  • I'm pretty sure the asker is looking for a dynamic implementation /sarcasm. Also, why use object literals for "data" instead of arrays? – Andy E Dec 10 '09 at 01:14