views:

90

answers:

4

I have 3 json arrays, each with information listed in the same format:

Array:
    ID:
    NAME:
    DATA:

    ID:
    NAME:
    DATA:

    etc...

My goal is to combine all 3 arrays into one array, and sort and display by NAME by passing the 3 arrays into a function.

The function I've tried is:

Javascript Call:

// to save time I'm just passing the name of the array, I've tried passing
// the full array name as json[0]['DATA'][array_1][0]['NAME'] as well.

combineNames(['array_1','array_2']);

FUNCTION:

function combineNames(names) {

    var allNames = []

    for (i=0;i<names.length;i++) {
        for (j=0;j<json[0]['DATA'][names[i]].length;j++) {
            allNames.push(json[0]['DATA'][names[i]][j]['NAME']);
        }
    }

    return allNames.sort();
}

The above gives me the error that NAME is null or undefined.

I've also tried using the array.concat function which works when I hard code it:

var names = [];
var allNames = [];

var names = names.concat(json[0]['DATA']['array_1'],json[0]['DATA']['array_2']);

for (i=0;i<names.length;i++) {
    allNames.push(names[i]['NAME']);
}

return allNames.sort();

But I can't figure out how to pass in the arrays into the function (and if possible I would like to just pass in the array name part instead of the whole json[0]['DATA']['array_name'] like I was trying to do in the first function...

A: 

You're redeclaring the allNames variable, emptying it.

Try this:

function combineNames(names) {
var allNames = [];
var data = json[0]['DATA'];
for (arrnames in data) {
    for (j=0;j<data[arrnames].length;j++) {
        if ('NAME' in data[arrnames]){
          allNames.push(data[arrnames]['NAME']);
        }
    }
}
return allNames.sort();
}
CodeJoust
Not sure where I'm redeclaring the allNames var? I get an objected expected error on the for (j=0;j<data[arrnames])... line of your code. Wouldn't you have to declare what arrnames is? Also for the push part, data[arrnames]['NAME'] is the incorrect format. As arrname is an array with several names, so you'd have to iterate through it as data[arrnames][j]['NAME'], I believe.
George
Ok... you redeclared the names variable when you wrote `var names = [];`, which overwrites the names array passed to the function as an empty array.
CodeJoust
Oh right, removed it that in the code I posted just now. My problem is still the same though. When I test it by commenting out the for loop and just return names.length I get 3 (the number or arrays I'm passing into it). When I return json[0]['DATA'][names[0]].length I get the correct number of names in the first array, and when I return json[0]['DATA'][names[0]][0]['NAME'] I get the first name in the first array. It's when I put it all together in the for loop and try to return allNames that it gets screwed up. Thanks for your help so far.
George
+1  A: 

If you've got 3 arrays like this:

[{ "id":1, "name":"Bob", "data":1},{ "id":2, "name":"Fred", "data":2 }]

Simply do:

function combine() {
    var ar = [];

    return ar.concat.apply(ar, arguments).sort(function (a, b) {
        var aName = a.NAME;
        var bName = b.NAME;
        if (aName < bName) {
            return -1;
        } else if (aName == bName) {
            return 0;
        } else {
            return 1;
        };
    });
};

Then call it like:

var jointArrays = combine(array1, array2, array3, ...);

However, if your JSON looks like this:

json[0]['DATA'][array_1]
json[0]['DATA'][array_2]
json[0]['DATA'][array_3]

You can simply define combine() as follows, which will be more convenient:

function combine(arrays) {
    var ar = [];

    return ar.concat.apply(ar, arrays).sort(function (a, b) {
        var aName = a.NAME;
        var bName = b.NAME;
        if (aName < bName) {
            return -1;
        } else if (aName == bName) {
            return 0;
        } else {
            return 1;
        };
    });
};

Then call it like:

var jointArrays = combine(json[0].DATA);

If you're wanting an array of just the names, rather than the objects, use the following:

function combine(arrays) {
    var ar = [],
        ret = [];

    ar = ar.concat.apply(ar, arrays);

    for (var i=0;i<ar.length;i++) {
        ret.push(ar.NAME);
    };

    return ret.sort();
};

Javascript is case sensitive; make sure it's DATA and not data, and NAME and not name.

Now for a little bit of housekeeping.

In your example, both of your counter variables are being declared as "implied globals", because you're not prefixing them with the var statement (and implied globals are bad). You should use:

for (var i=0;i<something.length;i++) {
   //
};

Instead of neglecting the var.

Also, "{}" creates an object. "[]" creates an array. Javascript does not support associative array's; e.g array's with keys that are anything except a number. What you're JSON is returning is an array of objects

"Square notation" and "dot notation" are interchangeable. object["one"] is equivalent to object.one

Square notation is generally used when the key is stored as a variable, or when you're accessing an array.

var key = "one";
object[key]

Hope this helps.

Matt
Thanks Matt. When you say to call it like array1, array2, do you mean the full json[0]['DATA']['array1']? When I do that I get [object, object][object, object], etc...
George
@George: You should do: `combine(json[0].DATA[array_one], json[0].DATA[array_two])`, but see my edit for a better solution (`combine(json[0].DATA)`).
Matt
Thanks for all your help Matt. Especially for pointing out the "house cleaning" stuff. I think your function was one step away. I still get [object, object] and it's probably just a misunderstanding of the hierarchy of my json arrays. In any case, my original function somehow now works @_@
George
@George: Not a problem. Just for the record, I was returning an array of the objects, rather than just the names. you can see my additional edit to see how I'd return only an array of the names.
Matt
A: 
function allNames(names) {

var allNames = [];

for (var i=0;i<names.length;i++) {
    for (var j=0;j<json[0]['DATA'][names[i]].length;j++) {
        allNames.push(json[0]['DATA'][names[i]][j]['NAME']);
    }
}

return allNames.sort();

}

called using:

allNames(['array_1','array_2']);

Seems to work.

George
+1  A: 

you can combine JSON easily with jQuery :

var x ={ a:1, b:2 };
var y ={ a:2, c:3 };
var z ={ b:3, d:4 };

$.extend(x, y, z);

console.dir(x); // now x is all of them combined
vsync