2016-12-16 31 views
1

我使用D3和需要根據行索引合併2個陣列上的可視化工作合併2個陣列:D3 - 如何根據自己的行索引

var links = 
[ 
{"source":"a0","target":"a0","s_portfolio":"a","t_portfolio":"a","SOURCE_TYPE":"APP","DES_TYPE":"APP"}, 
{"source":"a1","target":"a2","s_portfolio":"a","t_portfolio":"c","SOURCE_TYPE":"APP","DES_TYPE":"APP"}, 
{"source":"a1","target":"a2","s_portfolio":"a","t_portfolio":"c","SOURCE_TYPE":"APP","DES_TYPE":"APP"} 
]; 

var files = 
[ 
{"File_Desc":"","DataName":""}, 
{"File_Desc":"Date","DataName":"Dates.01012016"}, 
{"File_Desc":"Address","DataName":"Address.01012016"}  
    ]; 

要獲取:

var result = 
[ 
{"source":"a0","target":"a0","s_portfolio":"a","t_portfolio":"a","SOURCE_TYPE":"APP","DES_TYPE":"APP","File_Desc":"","DataName":""}, 
{"source":"a1","target":"a2","s_portfolio":"a","t_portfolio":"c","SOURCE_TYPE":"APP","DES_TYPE":"APP","File_Desc":"Date","DataName":"Dates.01012016"}, 
{"source":"a1","target":"a2","s_portfolio":"a","t_portfolio":"c","SOURCE_TYPE":"APP","DES_TYPE":"APP","File_Desc":"Address","DataName":"Address.01012016"} 
] 
+2

如果這些是您將要使用的數據,那麼只需手動合併它們並刪除問題。如果數據來自兩個文件或數據源,並且數據非常大,則難以手動處理,而您需要使用腳本來完成。你可以利用經典的「for」循環,其中每個鏈接對每個結果進行覈對,即一對一關係。有沒有解釋一些具體的要求? – Vlad

+0

@Vlad - 數據集來自1個文件,它非常大。我正在研究鏈接寬度基於連接數量的強制有向圖。當我試圖傳遞整個數組(無需將它分成兩個)時,我無法計算節點之間的連接數量。 – Alexey

+1

任何種類的圖形實際上都是一種數據結構,因此您應該將其視爲數據結構。圖是包含節點之間的節點和鏈接的結構。您可以使用鄰接矩陣來解釋哪個節點與哪個節點連接。當然,爲鏈接添加更多細節,也許可以根據鏈接到一個節點計算的鏈接權重可能? – Vlad

回答

3

如果你可以使用最新型號的JavaScript(又名ES2015), 的最短路徑是這樣的:

var result = links.map((d,i) => Object.assign({}, d, files[i])); 

這是短暫的。它也不會修改linksfiles(如果您希望將它們與result分開單獨使用)。

P.S.

評論顯示您關注替代解決方案的運行時間。一般來說,他們都可以,尤其是。作爲d3應用中常見的一種一次性數據設置。但是,如果您有大型數據集或經常進行記錄合併,那麼您可能需要優化。

如果你願意來更新現有的記錄集之一,而不是創建一個全新的一個:

links.forEach((d,i) => Object.assign(d, files[i])); 

在此之後,links有更新的記錄。這比其他解決方案運行速度快7-10倍,大概是因爲它不會創建大量新對象。如果您完成了原始的,未合併的對象linksfiles,沒有特別的理由來避免這種「破壞性」或「就地」更新。通常很少需要優化一次性設置操作。但如果你想要或需要這樣做,這是一個強有力的方法。

+0

謝謝!這很好。與下面的@dave建議有什麼不同? – Alexey

+2

@Alexey兩者都以單位數毫秒完成,但dave的速度更快。如果您正在處理大型數據集或執行數百或數千次操作,則增量可能會很大。在大多數情況下,事實並非如此。如果你只是作爲數據初始化的一部分來做這件事,那麼它並不重要。 –

0

使用jQuery map()和擴展()方法:

function mergeObjectsInArrays(arr1, arr2){ 
    return $.map(arr1, function(el, i){ 
     return $.extend(el, arr2[i]); 
    }); 
}; 

// then pass your arrays: 
var result = mergeObjectsInArrays(links, files); 
+1

OP可能不會使用jQuery。如果他不是,我沒有理由介紹它。這在香草JS中可以很容易地完成。 – dave

+0

公平點,@dave。 – chester

+0

並感謝您提供洞察,@dave。我很好奇爲什麼我的回答會被低估。 – chester

3

試試這個:

var links = [ 
 
    {"source":"a0","target":"a0","s_portfolio":"a","t_portfolio":"a","SOURCE_TYPE":"APP","DES_TYPE":"APP"}, 
 
    {"source":"a1","target":"a2","s_portfolio":"a","t_portfolio":"c","SOURCE_TYPE":"APP","DES_TYPE":"APP"}, 
 
    {"source":"a1","target":"a2","s_portfolio":"a","t_portfolio":"c","SOURCE_TYPE":"APP","DES_TYPE":"APP"} 
 
]; 
 

 
var files = [ 
 
    {"File_Desc":"","DataName":""}, 
 
    {"File_Desc":"Date","DataName":"Dates.01012016"}, 
 
    {"File_Desc":"Address","DataName":"Address.01012016"}  
 
]; 
 

 
var result = []; 
 

 
for(let i = 0; i < links.length; i++){ 
 
    result[i] = Object.assign(links[i], files[i]); 
 
} 
 

 
console.log(result);

+0

當我運行console.log(result); File_Desc和DataName在任何地方都是空的。任何想法爲什麼? – Alexey

+1

@Alexey你的結果[0] [「DataName」] ===「」'所以它只會顯示'console.log(result [1] [「DataName」]);'打印'Dates.01012016'。如果你的'console.log(result [1] [「DataName」]);'輸出了其他內容,那麼你的代碼在其他地方有問題。 – brigysl

2

我可能遍歷一個陣列與array map,然後在我的回調函數返回使用的功能的組合的對象,如在this answer定義的一個。

var result = links.map(combineLinkToFile); 

function combineLinkToFile (link, index) { 

    var file = files[index]; 

    return collect(link, file) 
} 

function collect() { 
    var ret = {}; 
    var len = arguments.length; 
    for (var i=0; i<len; i++) { 
    for (p in arguments[i]) { 
     if (arguments[i].hasOwnProperty(p)) { 
     ret[p] = arguments[i][p]; 
     } 
    } 
    } 
    return ret; 
} 
+0

謝謝!這很好。與@Jonathan Eunice在上面所建議的有什麼不同? – Alexey

+0

我不知道性能差異。如果這對你很重要,可能最好測試一下自己。但Object.assign的瀏覽器支持更有限,因此您可能不想將其用於前端。如果你能夠使用Object.assign,我更喜歡Jonathan的回答。 – dave