2011-08-31 24 views
15

有沒有什麼方法可以有效地加入JSON數據?假設我們有兩個JSON數據集:JSON數據的SQL風格JOIN

{"COLORS":[[1,red],[2,yellow],[3,orange]]} 

{"FRUITS":[[1,apple],[2,banana],[3,orange]]} 

而且我想這變成下面的客戶端:

{"NEW_FRUITS":[[1,apple,red],[2,banana,yellow],[3,orange,orange]]} 

記住會有成千上萬的在這裏記錄的與更復雜的數據結構。 jQuery和香草JavaScript都很好。另外請記住,沒有水果和水果的顏色可能沒有顏色。

注意:爲簡單起見,假設兩個數據集的順序都是相同的,但第二個數據集可能有間隙。

+0

好問題,但你沒有這兩個JSON數據集,你有兩個JavaScript對象;你不想加入JSON數據,你想加入對象。 – nnnnnn

+0

誰說他們是JS對象? OP可能指的是兩個JSON字符串。 –

+0

關於差異的細節信息在我身上丟失了,但我可以告訴你,我正在展示我正在使用的截斷版本。 –

回答

2

有沒有直接的方法,但你可以寫一個邏輯來得到這樣的組合對象。由於「蘋果,紅色,香蕉......」,它們都是字符串,因此應該用單引號或雙引號包裹。

如果您可以通過爲缺失的項目添加空值來匹配COLORS和FRUITS配置數組,那麼您可以使用此方法。

Wroking demo

var colors = {"COLORS":[[1,'red'],[2,'yellow'],[3,'orange']]} 

var fruits = {"FRUITS":[[1,'apple'],[2,'banana'],[3,'orange']]} 

var newFruits = {"NEW_FRUITS": [] } 

//Just to make sure both the arrays are of same size, otherwise the logic will break 
if(colors.COLORS.length == fruits.FRUITS.length){ 
    var temp; 
    $.each(fruits.FRUITS, function(i){ 
     temp = this; 
     temp.push(colors.COLORS[i][2]); 
     newFruits.NEW_FRUITS.push(temp); 
    }); 
} 

Alernatively如果你可以創建colorsfruits CONFIGS爲對象而不是數組的數組,你可以試試這個解決方案,它不關心元素的順序的排列但仍數組的大小應與

工作demo

var colors = {"COLORS":[ {"1": 'red'}, { "2": 'yellow'}, {"3":'orange'}]} 

var fruits = {"FRUITS":[ {"1":'apple'}, { "2": 'banana'}, {"3":'orange'}]} 

var newFruits = {"NEW_FRUITS": [] } 

if(colors.COLORS.length == fruits.FRUITS.length){ 
    var temp, first; 
    $.each(fruits.FRUITS, function(i){ 
     for(first in this)break; 
     temp = {}; 
     temp[first] = []; 
     temp[first].push(this[first]); 
     temp[first].push(colors.COLORS[i][first]); 
     newFruits.NEW_FRUITS.push(temp); 
    }); 
} 
+0

但問題是數組可能不是以相同的順序,因此您需要匹配所提供的數字ID,而不是基於數組索引。 – nnnnnn

+0

我在我的回答中提到只有在匹配時才嘗試。因爲如果我們儘可能避免客戶端的條件,它們將會是更多的元素。 – ShankarSangoli

+0

我編輯的問題說,他們是在相同的順序,因爲添加到各種SQL語句的排序是微不足道的。 –

9

事實上,將有成千上萬的輸入和密鑰不一定有序意味着你最好的選擇(至少對於大型對象)是先按鍵排序。對於尺寸小於5左右的物體,蠻力n^2方法就足夠了。

然後,您可以通過並行瀏覽兩個數組來寫出結果,並在輸出時添加新的「記錄」。這種排序然後合併的想法是一個相對強大的想法,並經常使用。如果您不想首先排序,則可以將元素添加到優先級隊列,然後按順序進行合併。排序然後合併的方法在概念上可能更簡單,如果性能很重要,你應該做一些分析。

對於無水果和無水果的顏色,我認爲編寫null缺失的值就足夠了。如果同一按鍵在顏色或水果中出現一次以上,您可以任意選擇一個,也可以拋出異常。

附錄我也做了一個小提琴:http://jsfiddle.net/LuLMz/。它不會對密鑰的順序做任何假設,也不會對陣列的相對長度進行任何假設。唯一的假設是字段的名稱和每個子陣列都有兩個元素的事實。

7

Alasql的JavaScript SQL庫不正是你需要在一行的內容:

<script src="alasql.min.js"></script> 
<script> 
    var data = { COLORS: [[1,"red"],[2,"yellow"],[3,"orange"]],    
       FRUITS: [[1,"apple"],[2,"banana"],[3,"orange"]]}; 

    data.NEW_FRUITS = alasql('SELECT MATRIX COLORS.[0], COLORS.[1], FRUITS.[1] AS [2] \ 
     FROM ? AS COLORS JOIN ? AS FRUITS ON COLORS.[0] = FRUITS.[0]', 
     [data.COLORS, data.FRUITS]); 
</script> 

您可以用的jsfiddle this example玩。

這是一個SQL表達式,其中:

  • 選擇 - 選擇操作者
  • MATRIX - 改性劑,從WHCI對象的數組轉換結果集到陣列
  • 顏色的數組[0] - COLORS陣列的第一列等。
  • FRUITS。 1 AS 2 - 陣列FRUITS的第二列將作爲第三列存儲在結果記錄集中
  • FROM? AS COLORS - 來自SQL語句中名爲COLORS的參數的數據數組
  • JOIN? ON ... - 加入
  • [data.COLORS,data.FRUITS] - 參數與數據陣列