[英]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()
或迭代b
和remove()
每個更改的數量有所顧慮。 那些改變了列表。
或者您可以使用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。 除了產生正確的結果之外,該技術還具有不為每個映射條目實例化新列表的優點。
請注意 ,必須明確地將b
為Object
。 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.