簡體   English   中英

Golang for 似乎跳過了一些實體

[英]Golang for seems to be skipping some entities

所以我有一個這樣的out字符串:

out := 
    "mobile" + "\n" + 
    "mobile/communicators" + "\n" + 
    "mobile/communicators/mock" + "\n" + 
    "mobile/handlers" + "\n" + 
    "mobile/mocks" + "\n" + 
    "mobile/models" + "\n" + 
    "mobile/requests"

我試圖將其轉換為切片,然后刪除pkgsToIgnore切片中具有匹配子字符串的pkgsToIgnore

pkgs := strings.Split(strings.TrimSpace(string(out)), "\n")

pkgsToIgnore := []string{"mock", "models"}

for i, pkg := range pkgs {
    for _, pkgToIgnore := range pkgsToIgnore {
        if strings.Contains(pkg, pkgToIgnore){
            pkgs = append(pkgs[:i], pkgs[i+1:]...)
        }
    }
}

for _, pkg := range pkgs {
    fmt.Println(pkg)
}

然后這是我從Println迭代中得到的結果:

mobile
mobile/communicators
mobile/handlers
mobile/models
mobile/requests

我的代碼似乎適用於包含mock作為子字符串的行,因為它們被刪除了。 但我不明白為什么mobile/models沒有。

查看正在發生的事情的最簡單方法是在每次迭代期間輸出ipkg ,即

for i, pkg := range pkgs {
        fmt.Println(i, pkg)
        for _, pkgToIgnore := range pkgsToIgnore {
            if strings.Contains(pkg, pkgToIgnore) {
                pkgs = append(pkgs[:i], pkgs[i+1:]...)
            }
        }
    }

這個的輸出是:

0 mobile
1 mobile/communicators
2 mobile/communicators/mock
3 mobile/mocks
4 mobile/requests
5 mobile/requests
6 mobile/requests

這可能不是您所期望的! 原因是您在迭代它的同時從pkgs中刪除元素。 讓我們在 i = 2 時解決這個問題; pkg == "mobile/communicators/mock" 所以字符串將從pkgs刪除。 pkgs元素 2 現在是“移動/處理程序”。 我們循環到for並移動到下一個元素 (3),即“移動/模擬”(不是“移動/處理程序”——現在是元素 2,因此“移動/處理程序”不會被檢查)。

go 規范的相關部分可能有助於理解這一點:

對於數組、數組指針或切片值 a,索引迭代值按遞增順序生成,從元素索引 0 開始。如果最多存在一個迭代變量,則范圍循環生成從 0 到 len( a)-1 並且不索引到數組或切片本身。 對於 nil 切片,迭代次數為 0。

可以像這樣在循環中更新切片,但這樣做 需要小心 通常將要保留的元素復制到新切片中更簡單。

有幾種方法可以做到這一點而不會意外跳過元素。 一種方法是簡單地將您想要的元素復制到臨時切片中,然后在完成所有操作后替換原始元素(這樣更難犯錯誤)。 但是,如果您不喜歡那樣,使用兩個索引會有所幫助:

src, dst := 0, 0
for src < len(pkgs) {
    var ignored bool
    for _, pkgToIgnore := range pkgsToIgnore {
        if strings.Contains(pkg, pkgToIgnore) {
            ignored = true
            break
        }
    }
    if !ignored {
        pkgs[dst] = pkgs[src]
        dst += 1
    }
    src += 1
}

pkgs = pkgs[:dst]

src范圍從 0 到pkgs的最后一個索引; dst將始終小於或等於src (因此我們永遠不會覆蓋我們尚未見過的元素); 每個元素只復制一次,到其最終目的地,而不是每次刪除一個元素時將所有元素左移一個(這可能是二次的)。 切片的長度只在最后調整,以反映實際保留的元素數量。

暫無
暫無

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

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