web-dev-qa-db-ja.com

golangのループで構造体配列の要素を削除する方法

問題

構造体の配列があります:

type Config struct {
  Applications []Application
}

注:Config-json.Decodeの構造体です。

config = new(Config)
_ = decoder.Decode(&config)

ループでは、いくつかの条件とキーによる要素の削除があります。

for i, application := range config.Applications {
  if i == 1 {
    config.Applications = _removeApplication(i, config.Applications)
  }
}

func _removeApplication(i int, list []Application) []Application {
  if i < len(list)-1 {
    list = append(list[:i], list[i+1:]...)
  } else {
    log.Print(list[i].Name)
    list = list[:i]
  }

  return list
}

しかし、常に「範囲外」エラーが発生します。構造体の配列からキーで要素を削除する最良の方法は何ですか?

17
Alex Pliutau

インデックスiの要素を削除する Slice Tricks ページからの引用:

a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]

現在ループしているスライスから要素を削除する場合は、問題が発生する可能性があることに注意してください。また、削除した要素が現在の要素(または既にループされた前の要素)である場合は、削除後に後続のすべての要素がシフトされますが、rangeループはこれを認識せず、引き続きインクリメントしますインデックスと1つの要素をスキップします。

これを回避するには、下向きのループを使用します。

for i := len(config.Applications) - 1; i >= 0; i-- {
    application := config.Applications[i]
    // Condition to decide if current element has to be deleted:
    if haveToDelete {
        config.Applications = append(config.Applications[:i],
                config.Applications[i+1:]...)
    }
}
40
icza

このエラーが発生するのは、ループ中に一部の要素を削除したためにX-nになった初期長X範囲のスライスでループを実行しているためです。

スライスから特定のインデックスにあるアイテムを削除する場合は、次の方法で行うことができます。

sliceA = append(sliceA[:indexOfElementToRemove], sliceA[indexOfElementToRemove+1:]...)
4
gdg

この質問は少し古いですが、リストをフィルタリングするための Slice Tricks からの次のトリックについて言及しているStackOverflowで別の回答を見つけていません。

b := a[:0]
for _, x := range a {
    if f(x) {
        b = append(b, x)
    }
}

したがって、この場合、特定の要素を削除する関数は次のようになります。

func removeApplications(apps []Applications) []Applications {
    filteredApps := apps[:0]
    for _, app := apps {
        if !removeApp {
            filteredApps = append(filteredApps, app)
        }
    }
    return filteredApps
}
3
treigerm

簡単な方法だと思います

var (
  slice = []int{1,2,3,4,5}
  pos int
)
    for _, i := range slice {
        if i == 3 {
            slice = append(slice[:pos], slice[pos+1:]...)
            if pos > 0 {
                pos = pos - 1
            }
            continue
        }
        pos++
    }

これは... https://play.golang.org/p/pK3B5Mii9k

1
Martin Prestone