簡體   English   中英

Groovy在迭代地圖時修改地圖元素

[英]Groovy modify map elements while iterating a map

我需要在迭代地圖時修改地圖元素,在我的情況下減去一些元素(列表)。 像這樣:

def a = [
   1: [1, 2, 3],
   2: [3, 2, 4],
   3: [3, 2, 4],
   4: [5, 2, 1],
]
def b = [3]
println a
a.values().each{ tr ->
   tr = tr - b
}
println a

a地圖上並沒有改變。 結果是:

[1:[1, 2, 3], 2:[3, 2, 4], 3:[5, 3, 1], 4:[5, 2, 1]]
[1:[1, 2, 3], 2:[3, 2, 4], 3:[5, 3, 1], 4:[5, 2, 1]]

但是,我希望結果是[1:[1, 2], 2:[2, 4], 3:[5, 1], 4:[5, 2, 1]] 我做錯了什么? 由於初始地圖​​相當大,我不想構建具有較少元素的另一個地圖(結果地圖)。

直接在地圖上工作:

a.keySet().each{
    a[it]-=b
}

在您的代碼中,您將結果分配給局部變量。

如果您對可能會考慮使用removeAll()或迭代bremove()每個更改的數量有所顧慮。 那些改變了列表。

或者您可以使用collectEntries

def a = [
   1: [1, 2, 3],
   2: [3, 2, 4],
   3: [3, 2, 4],
   4: [5, 2, 1],
]
def b = [3]

a = a.collectEntries { k, v -> [k, v - b] }

首先,我建議使用普通的vanilla Java List.remove(Object)而不是Groovy的List.minus(List) 那,是改變線條:

def b = [3]

tr = tr - b

進入以下內容:

def b = 3

tr.remove((Object)b)

前一對語句的問題是表達式tr - b創建了一個新的列表對象。 該列表分配給局部變量tr 同時原始列表,即駐留在Map中的列表,在賦值之前的tr的原始值保持不變。

顯式List.remove(Object)方法雖然不像減法那樣“Groovy”,但它在原始列表上運行而不創建新的List。 除了產生正確的結果之外,該技術還具有不為每個映射條目實例化新列表的優點。

請注意 ,必須明確地將bObject Groovy執行動態分派以解決運算符重載問題。 如果沒有強制轉換,即使靜態類型的b已經是Object ,Groovy也會檢測到b是一個整數並調用List.remove(int)而不是List.remove(Object) ,這將失敗。 演員陣容中,Groovy有足夠的暗示做正確的事情。


其次,我建議使用Map.each而不是Map.values()鏈接到List.each 從而替換這一行:

 a.values().each { tr -> 

以下內容:

 a.each { key, tr -> 

前一個語句使映射實例化包含所有值的列表,而后一個語句則不實例化。 雖然第一種情況下的實際“值”與地圖中的值相同,但您曾說過地圖太大而您不想創建一個全新的地圖。 所以我同樣假設你不想從地圖的價值對象中創建一個完整的列表。


如果您遵循這些建議,您的最終代碼應如下所示:

 def a = [ 1: [1, 2, 3], 2: [3, 2, 4], 3: [3, 2, 4], 4: [5, 2, 1], ] def b = 3 println a a.each{ k, v -> v.remove((Object)b) } println a 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM