Gibt es eine Möglichkeit, Slices / Maps auf das Vorhandensein eines Werts zu überprüfen?
Ich möchte einem Slice nur dann einen Wert hinzufügen, wenn er im Slice nicht vorhanden ist.
Das funktioniert, aber es scheint ausführlich. Gibt es einen besseren Weg, dies zu tun?
orgSlice := []int{1, 2, 3}
newSlice := []int{}
newInt := 2
newSlice = append(newSlice, newInt)
for _, v := range orgSlice {
if v != newInt {
newSlice = append(newSlice, v)
}
}
newSlice == [2 1 3]
ints
im GAE-Datenspeicher und zum Abfragen muss es sich um ein Slice ([]int
) handeln. Macht diese Anforderung meine anfängliche Technik zur besseren Wahl? Die Listen werden klein sein.append()
(und alle Neuzuweisungen) vermeiden , indem Sie zunächst eine erstellennewslice := make([]int, len(set))
. Wenn Sie viele solcher "enthält den Schlüssel ..." - Tests durchführen (mindestens mehr als 2), ist die Konvertierung des Slice in eine Map [int] struct {} wahrscheinlich viel schneller, wenn Sie nur wenige Loops durchführen durch die Scheibe direkt ist wohl besser.Antworten:
Ihr Ansatz würde für jede Einfügung eine lineare Zeit in Anspruch nehmen. Ein besserer Weg wäre, a zu verwenden
map[int]struct{}
. Alternativ können Sie auch einmap[int]bool
oder ähnliches verwenden, aber das Leerestruct{}
hat den Vorteil, dass es keinen zusätzlichen Platz belegt. Dahermap[int]struct{}
ist eine beliebte Wahl für eine Reihe von ganzen Zahlen.Beispiel:
set := make(map[int]struct{}) set[1] = struct{}{} set[2] = struct{}{} set[1] = struct{}{} // ... for key := range(set) { fmt.Println(key) } // each value will be printed only once, in no particular order // you can use the ,ok idiom to check for existing keys if _, ok := set[1]; ok { fmt.Println("element found") } else { fmt.Println("element not found") }
quelle
Am effizientesten ist es wahrscheinlich, über das Slice zu iterieren und es anzuhängen, wenn Sie es nicht finden.
func AppendIfMissing(slice []int, i int) []int { for _, ele := range slice { if ele == i { return slice } } return append(slice, i) }
Es ist einfach und offensichtlich und wird für kleine Listen schnell sein.
Außerdem ist es immer schneller als Ihre aktuelle kartenbasierte Lösung. Die kartenbasierte Lösung iteriert über das gesamte Segment, egal was passiert. Diese Lösung wird sofort zurückgegeben, wenn festgestellt wird, dass der neue Wert bereits vorhanden ist. Beide Lösungen vergleichen Elemente, während sie iterieren. (Jede Kartenzuweisungsanweisung führt sicherlich intern mindestens einen Kartenschlüsselvergleich durch.) Eine Karte wäre nur dann nützlich, wenn Sie sie über viele Einfügungen hinweg pflegen könnten. Wenn Sie es bei jeder Einfügung neu erstellen, gehen alle Vorteile verloren.
Wenn Sie wirklich große Listen effizient bearbeiten müssen, sollten Sie die Listen in sortierter Reihenfolge verwalten. (Ich vermute, die Reihenfolge spielt für Sie keine Rolle, da Ihre erste Lösung am Anfang der Liste und Ihre neueste Lösung am Ende angehängt wird.) Wenn Sie die Listen immer sortiert halten, können Sie die Funktion sort.Search verwenden Führen Sie effiziente binäre Einfügungen durch.
quelle
Unterscheiden eines Arrays einer Struktur:
func distinctObjects(objs []ObjectType) (distinctedObjs [] ObjectType){ var output []ObjectType for i:= range objs{ if output==nil || len(output)==0{ output=append(output,objs[i]) } else { founded:=false for j:= range output{ if output[j].fieldname1==objs[i].fieldname1 && output[j].fieldname2==objs[i].fieldname2 &&......... { founded=true } } if !founded{ output=append(output,objs[i]) } } } return output }
wo die Struktur hier so etwas ist wie:
type ObjectType struct { fieldname1 string fieldname2 string ......... }
Das Objekt wird hier durch markierte Felder unterschieden:
if output[j].fieldname1==objs[i].fieldname1 && output[j].fieldname2==objs[i].fieldname2 &&......... {
quelle
package main import ( "fmt" "os" "reflect" ) func main() { /* s := []string{"a", "b"} fmt.Println(s) s = AppendIfMissing(s, "4").([]string) fmt.Println(s)*/ /* var a []*string a = make([]*string, 0) e := "4" a = AppendIfMissing(a, &e).([]*string) fmt.Println(*a[0])*/ var a []*float64 a = make([]*float64, 3) e := 4.4 d := 4.41 a = AppendIfMissing(a, &e).([]*float64) a = AppendIfMissing(a, &d).([]*float64) fmt.Println(*a[3], *a[4]) } func AppendIfMissing(array interface{}, element interface{}) interface{} { if reflect.ValueOf(array).IsNil() { fmt.Fprintf(os.Stderr, "array not initialized\n") return nil } switch reflect.TypeOf(array).Kind() { case reflect.Slice: arrayV := reflect.ValueOf(array) arrayVLen := arrayV.Len() if arrayVLen == 0 {//if make len == 0 sliceNew := reflect.MakeSlice(reflect.ValueOf(array).Type(), 1, 1) if sliceNew.Index(0).Type() != reflect.ValueOf(element).Type() { fmt.Fprintf(os.Stderr, "types are not same\n") return sliceNew.Interface() } sliceNew.Index(0).Set(reflect.ValueOf(element)) return sliceNew.Interface() } for i := 0; i < arrayVLen; i++ { if i == 0 && reflect.ValueOf(element).Kind() != arrayV.Index(i).Kind() { fmt.Fprintf(os.Stderr, "types are not same\n") return array } if arrayV.Index(i).Interface() == element { return array } } default: fmt.Fprintf(os.Stderr, "first element is not array\n") return array } arrayV := reflect.ValueOf(array) elementV := reflect.ValueOf(element) appendAE := reflect.Append(arrayV, elementV) return appendAE.Interface() }
quelle