2016-03-28 92 views
1

我有2個ArrayList。一個是[[帳戶:價值,預算:價值]],另一個是[[帳戶:價值,cYBudget:價值]]我想結束以下格式的列表:[[帳戶:價值,預算:價值,cYBudget:值]]將新的鍵值對添加到陣列列表

的數據的一個例子是:

budProp = [[ACCTCODE:6201,BUDGET:2500],[ACCTCODE:7999,BUDGET:1500]

budCyExp = [[ACCTCODE:6201,cYBudget:1000],[ACCTCODE:7999,cYBudget:2000]]

我想的結果:

[[ACCTC ODE:6201,BUDGET:2500,cYBudget:1000],[ACCTCODE:7999,BUDGET:1500,cYBudget:2000]]

基本上我通過匹配ACCTCODE來「合併」兩個列表並確保每個列表包含ACCTCODE,BUDGET和cYBudget鍵/值對。 Groovy是否有一些方法可以做到這一點?

我正在使用Groovy 2.3.7

謝謝。

回答

0

的方法GroovyCollections#transpose()可以從兩個列表生成對的列表:

groovy:000> [[1,2,3], [4,5,6]].transpose() 
===> [[1, 4], [2, 5], [3, 6]] 

如果你有在同一順序相同的帳戶代碼的兩個列表,你可以壓縮並行列表條目成對的地圖用轉置方法,然後合併各對的地圖:

[budProp, budCyExp].transpose().collect { it[0] + it[1] } 

以下是groovysh細分,以便可以看到分別調換的結果如下步驟:

groovy:000> budProp = [[ACCTCODE:6201, BUDGET:2500], [ACCTCODE:7999, BUDGET:1500]] 
===> [[ACCTCODE:6201, BUDGET:2500], [ACCTCODE:7999, BUDGET:1500]] 
groovy:000> budCyExp = [[ACCTCODE:6201,cYBudget:1000],[ACCTCODE:7999,cYBudget: 2000]] 
===> [[ACCTCODE:6201, cYBudget:1000], [ACCTCODE:7999, cYBudget:2000]] 
groovy:000> [budProp, budCyExp].transpose() 
===> [[[ACCTCODE:6201, BUDGET:2500], [ACCTCODE:6201, cYBudget:1000]], [[ACCTCODE:7999, BUDGET:1500], [ACCTCODE:7999, cYBudget:2000]]] 
groovy:000> _.collect { it[0] + it[1] } 
===> [[ACCTCODE:6201, BUDGET:2500, cYBudget:1000], [ACCTCODE:7999, BUDGET:1500, cYBudget:2000]] 

在現實生活中,我會猶豫不決,除非我100%確定平行列表完美排列(一個列表中的每個帳戶代碼都在另一個列表中),否則我會做類似的事情:

groovy:000> budMap = budProp.inject([:]) { m, e -> m[e['ACCTCODE']] = e['BUDGET']; m } 
===> [6201:2500, 7999:1500] 
groovy:000> cyMap = budCyExp.inject([:]) { m, e -> m[e['ACCTCODE']] = e['cYBudget']; m } 
===> [6201:1000, 7999:2000] 
groovy:000> (budMap.keySet() + cyMap.keySet()).collect { [ACCTCODE: it, BUDGET: budMap[it], cYBudget: cyMap[it] ] } 
===> [[ACCTCODE:6201, BUDGET:2500, cYBudget:1000], [ACCTCODE:7999, BUDGET:1500, 
cYBudget:2000]] 

這並不短,但它處理的情況是一個列表中的賬戶沒有在另一個列表中表示。

+0

非常感謝。這正是我需要的。你對這些列表沒有完全排隊,他們沒有,但我認爲一個答案會指向正確的方向,我必須弄清楚其餘的,但是你給了我所需要的全部內容它。 – Greg

0

在名單不排隊完美的情況下,這將是更適合使用Groovy的Iterable.groupBy(Closure)方法:

def budProp = [[ACCTCODE:6201, BUDGET:2500], [ACCTCODE:7999, BUDGET:1500]] 
def budCyExp = [[ACCTCODE:7999,cYBudget: 2000], [ACCTCODE:6201,cYBudget:1000]] 

def budMaster = (budProp + budCyExp) 
println budMaster 
//[[ACCTCODE:6201, BUDGET:2500], [ACCTCODE:7999, BUDGET:1500], [ACCTCODE:7999, cYBudget:2000], [ACCTCODE:6201, cYBudget:1000]] 

def budMappedAcct = budMaster.groupBy { it.ACCTCODE } 
println budMappedAcct 
// [6201:[[ACCTCODE:6201, BUDGET:2500], [ACCTCODE:6201, cYBudget:1000]], 7999:[[ACCTCODE:7999, BUDGET:1500], [ACCTCODE:7999, cYBudget:2000]]] 

def budMapList = budMappedAcct.collect { code, mapList -> mapList.sum() } 
println budMapList 
// [[ACCTCODE:6201, BUDGET:2500, cYBudget:1000], [ACCTCODE:7999, BUDGET:1500, cYBudget:2000]] 

這工作秩序和不匹配的列表超出太多,只要所有原始地圖都有ACCTCODE。如果需要,可以將此解決方案精簡爲一行:

def budMapList = (budProp + budCyExp).groupBy { it.ACCTCODE }.collect { code, mapList -> mapList.sum() } 
+0

感謝這個答案,我喜歡有多個解決方案的問題,它可以幫助我學習更多。唯一讓Nathan的解決方案更加適用的是,它將返回一個ACCTCODE,BUDGET和cYBudget,而不管ACCTCODE值是否在兩個列表中。例如,budProp可能有第三套ACCTCODE和BUDGET,它不存在於budCyExp中,所以它會返回[ACCTCODE:value,BUDGET:value,cYBudget:null]。我沒有足夠的聲望點將您的答案標記爲有用,但如果可以的話,我會盡可能。 – Greg

+0

不要出汗;我並不是真的在這裏提出觀點。此外,如果別人喜歡這個答案,他們會給它一個顛簸。 Java/Groovy默認映射語義確保如果您從地圖中請求一個沒有鍵的項目,地圖將返回空值。因此,即使您嘗試訪問密鑰,也不會在映射中顯式定義條目'cYBudget:null',否則結果將爲空:'answerMap.cYBudget == null'。所以從數據訪問的角度來看,結果是一樣的。 – BalRog

+0

啊,謝謝,那會有效。欣賞它。 – Greg