admin管理员组

文章数量:1293342

I've spent all morning messing with this now and reading on here, but have found myself going round in circles!

I am trying to draw a chart using the excellent AmCharts Javascript Charts, to show me stock holding as a bar chart and stock turn as a line chart.

I cannot get both sets of data from one query to my database, and cannot use AmCharts StockChart as it is not time based data... therefore, I have two sets of data which need bining with Javascript.

The data is being pulled from a database and returned successfully as JSON arrays similar to this:

SALES DATA:

[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
 {"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
 {"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}]

STOCK DATA:

[{"brandName":"Gibson","stockValue":"1234"},
 {"brandName":"Fender","stockValue":"975"},
 {"brandName":"Epiphone","stockValue":"834"}]

Obviously the actual figures are made up in that example!

Now, what I need to do is to bine those to create this:

COMBINED DATA

[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55","stockValue":"975"},
 {"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43","stockValue":"1234"},
 {"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13","stockValue":"834"}]

What we have there is the Sales Dataset bined with Stock Dataset to add the additional data of stockValue added to the corresponding brandName record.

I have tried using $.extend but I can't figure out how to use it in this situation.

It is perhaps important to note that the data pairs might not necessarily be in the right order, and it is possible, though unlikely, that there might not be a match, so some kind of zeroing error catching must be implemented.

I've spent all morning messing with this now and reading on here, but have found myself going round in circles!

I am trying to draw a chart using the excellent AmCharts Javascript Charts, to show me stock holding as a bar chart and stock turn as a line chart.

I cannot get both sets of data from one query to my database, and cannot use AmCharts StockChart as it is not time based data... therefore, I have two sets of data which need bining with Javascript.

The data is being pulled from a database and returned successfully as JSON arrays similar to this:

SALES DATA:

[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
 {"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
 {"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}]

STOCK DATA:

[{"brandName":"Gibson","stockValue":"1234"},
 {"brandName":"Fender","stockValue":"975"},
 {"brandName":"Epiphone","stockValue":"834"}]

Obviously the actual figures are made up in that example!

Now, what I need to do is to bine those to create this:

COMBINED DATA

[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55","stockValue":"975"},
 {"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43","stockValue":"1234"},
 {"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13","stockValue":"834"}]

What we have there is the Sales Dataset bined with Stock Dataset to add the additional data of stockValue added to the corresponding brandName record.

I have tried using $.extend but I can't figure out how to use it in this situation.

It is perhaps important to note that the data pairs might not necessarily be in the right order, and it is possible, though unlikely, that there might not be a match, so some kind of zeroing error catching must be implemented.

Share asked Jul 31, 2012 at 13:34 Jamie HartnollJamie Hartnoll 7,36114 gold badges63 silver badges100 bronze badges 1
  • Why can't you get both sets of data from one query? – Waleed Khan Commented Jul 31, 2012 at 13:44
Add a ment  | 

4 Answers 4

Reset to default 4

What you'll need to do first is transform the data into two objects, whose properties are the values you want to merge together:

{
"Fender" : {"gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
"Gibson" : {"gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
"Epiphone" : {"gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}
}

and

{
"Gibson": {"stockValue":"1234"},
"Fender": { "stockValue":"975"},
"Epiphone": { "stockValue":"834"}
}

Once the transformation is done, you'll have two objects that you can merge using $.extend or other functions.

Update

For large sets, this gives results in nearly linear time:

var salesa = {}, stocka = {};
$.each(sales, function(i, e) {
    salesa[e.brandName] = e;
});
$.each(stock, function(i, e) {
    stocka[e.brandName] = e;
});

var bine = {};
$.extend(true, bine, salesa, stocka)

More speed can be tweaked if the merging happened during the second transformation callback ($each(stock...) instead of a separate call to $.extend() but it loses some of its obviousness.

I think what's he's trying to do is join the two datasets as if they were tables, joining by the brandName. From what I've been testing jQuery's $.extend() function does not take care of that, but merges objects according to their index in the Object arrays that it receives.

I think the matching of the key would need to be done manually.

stock = [{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
 {"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
 {"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}];
value = [{"brandName":"Gibson","stockValue":"1234"},
 {"brandName":"Fender","stockValue":"975"},
 {"brandName":"Epiphone","stockValue":"834"}];

var results = [];
$(stock).each(function(){
    datum1 = this;
    $(value).each(function() {
        datum2 = this;
        if(datum1.brandName == datum2.brandName)
            results.push($.extend({}, datum1, datum2));
    });
});

Which would result in:

[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55","stockValue":"975"},
{"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43","stockValue":"1234"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13","stockValue":"834"}]

Instead of what the use of $.extend() returns:

[{"brandName":"Gibson","gearShiftedPerMonth":"35","retailSalesPerMonth":"55","stockValue":"1234"},
{"brandName":"Fender","gearShiftedPerMonth":"23","retailSalesPerMonth":"43","stockValue":"975"},
{"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13","stockValue":"834"}]

If your example code reflects reality, then jQuery's $.extend will be the wrong tool for this.

It blindly copies data from one object to another. Notice that the order of your data is not consistent. The SALES DATA has Fender first, while the STOCK DATA has gibson first.

So jQuery's $.extend is mixing the two results. The "gearShifted" and "retailSales" for Fender is ending up with the "brandName" and "stockValue" for Gibson.


What you'll need is to iterate one array, and look up the "brandName" in the other, and then copy over the data you want. You could use $.extend for that part of it if you like...

var sales_data = 
[{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
 {"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
 {"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}]

var stock_data = 
[{"brandName":"Gibson","stockValue":"1234"},
 {"brandName":"Fender","stockValue":"975"},
 {"brandName":"Epiphone","stockValue":"834"}]

var bined = $.map(sales_data, function(obj, i) {

    return $.extend({}, obj, $.grep(stock_data, function(stock_obj) {
        return obj.brandName === stock_obj.brandName
    })[0]);
});

Note that this is not terribly efficient, but unless the data set is enormous, it shouldn't be an issue.


DEMO: http://jsfiddle/sDyKx/

RESULT:

[
    {
        "brandName": "Fender",
        "gearShiftedPerMonth": "35",
        "retailSalesPerMonth": "55",
        "stockValue": "975"
    },
    {
        "brandName": "Gibson",
        "gearShiftedPerMonth": "23",
        "retailSalesPerMonth": "43",
        "stockValue": "1234"
    },
    {
        "brandName": "Epiphone",
        "gearShiftedPerMonth": "10",
        "retailSalesPerMonth": "13",
        "stockValue": "834"
    }
]

In vanilla javascript you can do:

var sales = [{"brandName":"Fender","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
 {"brandName":"Gibson","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
 {"brandName":"Epiphone","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}];

var stock = [{"brandName":"Gibson","stockValue":"1234"},
 {"brandName":"Fender","stockValue":"975"},
 {"brandName":"Epiphone","stockValue":"834"}];

var bined = stock.slice(0);     

for (var i = 0; i < stock.length; i++) {
    for (var j = 0; j < sales.length; j++) {
        if (stock[i].brandName === sales[j].brandName) {
            for (var attrname in sales[j]) { bined[i][attrname] = sales[j][attrname]; }
        }
    }
}

JSON.stringify(bined)

produces

[
{"brandName":"Gibson","stockValue":"1234","gearShiftedPerMonth":"23","retailSalesPerMonth":"43"},
{"brandName":"Fender","stockValue":"975","gearShiftedPerMonth":"35","retailSalesPerMonth":"55"},
{"brandName":"Epiphone","stockValue":"834","gearShiftedPerMonth":"10","retailSalesPerMonth":"13"}
]

本文标签: javascriptCombining JSON Arrays with jQueryStack Overflow