2012-07-31 13 views
5

Ich habe den ganzen Vormittag damit verbracht, hier zu blödeln und hier zu lesen, aber ich habe mich im Kreis herumtreiben sehen!JSON-Arrays mit jQuery kombinieren

Ich versuche, ein Diagramm zu zeichnen, das die ausgezeichneten AmCharts Javascript-Diagramme verwendet, um mich Lagerhaltung als Balkendiagramm zu zeigen und Vorrat als Liniendiagramm zu drehen.

Ich kann nicht beide Datensätze von einer Abfrage zu meiner Datenbank abrufen, und kann AmCharts StockChart nicht verwenden, da es keine zeitbasierten Daten ist ... daher habe ich zwei Datensätze, die mit Javascript kombiniert werden müssen.

Die Daten aus einer Datenbank gezogen und erfolgreich als JSON-Arrays ähnlich zu diesem Retour:

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"}] 

Offensichtlich sind die tatsächlichen Zahlen in diesem Beispiel zusammengesetzt!

Nun, was ich tun muss, ist jene, zu kombinieren, um diese zu erstellen:

kombinierten Daten

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

Was wir dort haben, ist der Umsatz Dataset kombiniert mit Vektor Dataset den zusätzlichen hinzufügen Daten von stockValue wurden dem entsprechenden BrandName-Datensatz hinzugefügt.

Ich habe versucht mit $.extend, aber ich kann nicht herausfinden, wie man es in dieser Situation verwendet.

Es ist vielleicht wichtig zu beachten, dass die Datenpaare nicht unbedingt in der richtigen Reihenfolge sind, und es ist möglich, obwohl es unwahrscheinlich ist, dass es keine Übereinstimmung gibt, so muss eine Art Nullabgleich Fehlerfang implementiert werden.

+0

Warum Sie bekommen können nicht beide Arten von Daten aus einer Abfrage? –

Antwort

2

Ich denke, was er die beiden Datensätze zu tun versucht wird kommen, als ob sie Tische, Beitritt durch den Markennamen. Von dem, was ich getestet habe, kümmert sich die $ .extend() - Funktion von jQuery nicht darum, sondern fügt Objekte gemäß ihrem Index in die Object-Arrays ein, die sie empfängt.

Ich denke, die Übereinstimmung des Schlüssels müsste manuell erfolgen.

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)); 
    }); 
}); 

, die in Folge hätte:

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

Statt dessen, was die Verwendung von $.extend() kehrt:

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

Das ist richtig. Siehe jedoch meine Antwort unten für einen etwas anderen Ansatz, der für sehr große Datenmengen auf Kosten des Speichers effizienter wäre. –

4

Was Sie zuerst tun müssen, um die Daten in zwei Objekte transformieren, deren Eigenschaften sind die Werte, die Sie wollen, zusammen fusionieren:

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

und

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

Sobald die Transformation Fertig, Sie haben zwei Objekte, die Sie mit $.extend oder anderen Funktionen zusammenführen können.

aktualisieren

Für große Mengen gibt diese Ergebnisse in nahezu lineare Zeit:

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

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

Mehr Geschwindigkeit optimiert werden kann, wenn die Verschmelzung während der zweiten Transformation Rückruf ($each(stock...) anstelle eines geschah separater Anruf an $.extend(), aber es verliert etwas von seiner Offensichtlichkeit.

+0

Keine Notwendigkeit, die Daten aus einem Array zu transformieren. – jholloman

+0

@jholloman: Durch die Umwandlung der Daten wird sichergestellt, dass die Daten zwischen den Markennamen übereinstimmen. Beachten Sie, dass in der Frage die Markennamen nicht konsistent mit den Array-Indizes übereinstimmen. +1 –

+0

Leider habe ich die falsche Annahme gemacht, dass die Extend-Lösung korrekt war. Was würdest du als effizienteste Methode vorschlagen, um zu einem Objekt zu transformieren? – jholloman

1

In Vanille javascript Sie tun können:

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 combined = 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]) { combined[i][attrname] = sales[j][attrname]; } 
     } 
    } 
} 

JSON.stringify(combined) 

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

Wenn Ihr Beispielcode Realität erzeugt reflektiert, dann $.extend jQuery wird das falsch Werkzeug dafür sein.

Es kopiert blind Daten von einem Objekt zu einem anderen. Beachten Sie, dass die Reihenfolge Ihrer Daten nicht konsistent ist. Die Verkaufsdaten haben zuerst Fender, während die Lagerdaten zuerst gibson haben.

So jQuery $.extend ist die beiden Ergebnisse zu mischen. Die "gearShifted" und "retailSales" für Fender endet mit "brandName" und "stockValue" für Gibson.


Was Sie brauchen, ist ein Array zu durchlaufen, und die „Marke“ in der anderen zu sehen, und kopieren Sie dann über die Daten, die Sie wollen. Sie könnten $.extend für diesen Teil davon verwenden, wenn Sie mögen ...

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 combined = $.map(sales_data, function(obj, i) { 

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

Beachten Sie, dass dies nicht sehr effizient ist, aber es sei denn, der Datensatz ist enorm, es sollte kein Problem sein.


DEMO:http://jsfiddle.net/sDyKx/

ERGEBNIS:

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

Ich dachte, ich hätte mich geirrt, wurde nach unten abgestimmt und löschte meine Antwort, um Unordnung zu reduzieren. Ich hätte an meinen Waffen festhalten sollen. –

+0

@clintp: Lösche deine Antwort und ich gebe dir +1. Ihnen ist eine weitere gute Lösung, wenn die Daten transformiert werden können. –

+0

Wenn Sie * wüssten *, dass es eine 1: 1-Beziehung gab, könnte es schneller sein, die Arrays nach dem 'brandName' zu ​​sortieren und dann von dort zu verschmelzen. Die Lösungen hier sind alle O (N * M) im schlechtesten Fall, und eine Sortierung könnte so niedrig wie O (log N * log M) sein. Aus diesem Grund habe ich zunächst einen transformativen Ansatz gewählt. –