it-swarm.com.de

Go: Anhängen, wenn eindeutig

Gibt es eine Möglichkeit, Slices/Karten auf Vorhandensein eines Wertes zu prüfen?

Ich möchte einem Slice einen Wert hinzufügenonly, wennnichtim Slice vorhanden ist. 

Das funktioniert, scheint aber ausführlich zu sein. 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]
43
Kyle Finley

Ihr Ansatz würde für jedes Einfügen lineare Zeit in Anspruch nehmen. Ein besserer Weg wäre die Verwendung eines map[int]struct{}. Alternativ können Sie auch einen map[int]bool oder ähnliches verwenden, der leere struct{} hat jedoch den Vorteil, dass er keinen zusätzlichen Speicherplatz belegt. Daher ist map[int]struct{} eine beliebte Wahl für eine Menge von Ganzzahlen.

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")
}
66
tux21b

Am effizientesten ist es wahrscheinlich, das Slice zu durchlaufen und anzufügen, 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 naheliegend und wird für kleine Listen schnell sein.

Außerdem ist es immer schneller als Ihre aktuelle kartenbasierte Lösung. Die kartenbasierte Lösung durchläuft die gesamte Schicht, egal was passiert; Diese Lösung wird sofort zurückgegeben, wenn der neue Wert bereits vorhanden ist. Beide Lösungen vergleichen Elemente bei ihrer Wiederholung. (Jede Map-Zuweisungsanweisung führt gewissermaßen intern mindestens einen Map-Schlüsselvergleich durch.) Eine Map wäre nur dann sinnvoll, wenn Sie sie über viele Einfügungen hinweg pflegen könnten. Wenn Sie es bei jedem Einfügen 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, dass die Reihenfolge für Sie keine Rolle spielt, da Ihre erste Lösung am Anfang der Liste und Ihre letzte Lösung am Ende angehängt wird.) Wenn Sie die Listen immer sortiert halten, können Sie die sort.Search-Funktion verwenden effiziente binäre Einfügungen durchführen.

29
Sonia

ein Array einer Struktur unterscheiden:

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: 

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 &&......... {
0
Bit
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()
}
0
book777