2012-07-31 101 views
5

我已經花了整整一個早上的時間搞清楚了這一點,並在這裏閱讀,但是發現自己正在圍繞着圈子!將JSON數組與jQuery結合使用

我正在嘗試使用出色的AmCharts Javascript圖表來繪製圖表,以顯示股票持有狀況,並以折線圖形式顯示股票。

我無法從一個查詢中獲取兩組數據到我的數據庫,也無法使用AmCharts StockChart,因爲它不是基於時間的數據......因此,我有兩組需要與Javascript結合的數據。

數據正在從數據庫中抽取,併成功地返回與此類似JSON數組:

銷售數據:

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

顯然,在這個例子中,實際數字就是這樣構成的!

現在,我需要做的是要結合這些創造這樣的:

組合數據

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

我們有什麼是銷售數據集結合庫存數據集,添加額外的將數據stockValue添加到相應的brandName記錄中。

我試過使用$.extend但我無法弄清楚如何在這種情況下使用它。

可能很重要的一點是,數據對可能不一定按照正確的順序排列,儘管不太可能,但可能沒有匹配,因此必須實施某種歸零錯誤捕獲。

+0

你爲什麼不能從一個查詢得到兩組數據的? – 2012-07-31 13:44:23

回答

2

我想他自己堅持要做,好像他們是表中加入了兩個數據集,由品牌名稱加入。從我一直在測試的jQuery的$ .extend()函數沒有考慮到這一點,但是根據它們在它接收到的Object數組中的索引合併對象。

我認爲密鑰的匹配需要手動完成。

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

這將導致:

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

而不是什麼用的$.extend()回報:

[{"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

這是正確的。不過,請參閱下面的答案,以稍微改變一下方法,以犧牲內存爲代價來提高非常大的數據集的效率。 – 2012-08-01 13:57:02

4

你需要首先做的是將數據轉換成兩個對象,你要合併在一起,其屬性是值:

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

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

一旦轉換爲完成後,您將有兩個對象,您可以使用$.extend或其他功能進行合併。

更新

對於大型集,這給出了在幾乎線性時間的結果:

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) 
如果第二變換回調( $each(stock...)在合併發生

更多速度可以調整,而不是一個單獨致電$.extend(),但它失去了一些顯而易見的性質。

+0

無需將數據轉換出陣列。 – jholloman 2012-07-31 13:44:25

+0

@jholloman:轉換數據將確保品牌名稱之間的數據匹配。請注意,在問題中,品牌名稱與數組索引不一致。 +1 – 2012-07-31 14:35:19

+0

對不起,我錯誤地認爲擴展解決方案是正確的。你會提出什麼樣的建議來作爲轉化爲對象的最有效方式? – jholloman 2012-07-31 14:42:03

1

在香草的JavaScript,你可以這樣做:

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

如果你的示例代碼反映現實,那麼jQuery的$.extend將是這個錯誤工具。

它將數據從一個對象盲目複製到另一個對象。請注意,您的數據的順序不一致。首先銷售數據有Fender,而股票數據首先有gibson

所以jQuery的$.extend混合了這兩個結果。 Fender的「gearShifted」和「retailSales」以Gibson的「brandName」和「stockValue」結尾。


你需要的是迭代一個數組,然後在另一個數組中查找「brandName」,然後複製你想要的數據。如果你喜歡,你可以使用$.extend爲它的一部分...

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

注意,這不是非常有效,但除非該數據集是巨大的,它不應該是一個問題。


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

結果:

[ 
    { 
     "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

我以爲我錯了,倒了票,並刪除了我的答案,以減少混亂。我應該堅持我的槍支。 – 2012-07-31 14:23:48

+0

@clintp:取消刪除你的答案,我會給你+1。如果數據可以轉換,你的另一個好的解決方案。 – 2012-07-31 14:27:41

+0

如果你知道有1:1的關係,那麼可以用'brandName'對數組進行排序,然後再從那裏合併。這裏的解決方案在最壞的情況下都是O(N * M),而排序可能低到O(log N * log M)。這就是爲什麼我首先採取了變革性的方法。 – 2012-07-31 14:43:09