web-dev-qa-db-fra.com

Go: Ajouter si unique

Existe-t-il un moyen de vérifier la présence d'une valeur dans les tranches/cartes?

Je voudrais ajouter une valeur à une trancheuniquementsi c'est le caspasexistent dans la tranche. 

Cela fonctionne, mais cela semble verbeux. Y at-il un meilleur moyen de faire cela?

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

Votre approche prendrait du temps linéaire pour chaque insertion. Un meilleur moyen serait d'utiliser un map[int]struct{}. Vous pouvez également utiliser un map[int]bool ou quelque chose de similaire, mais le struct{} vide présente l'avantage de ne pas occuper d'espace supplémentaire. Par conséquent, map[int]struct{} est un choix courant pour un ensemble d’entiers.

Exemple:

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

Le plus efficace consiste probablement à parcourir la tranche et à l'ajouter si vous ne la trouvez pas.

func AppendIfMissing(slice []int, i int) []int {
    for _, ele := range slice {
        if ele == i {
            return slice
        }
    }
    return append(slice, i)
}

C'est simple, évident et rapide pour les petites listes.

En outre, ce sera toujours plus rapide que votre solution actuelle basée sur des cartes. La solution basée sur la carte itère sur toute la tranche, peu importe quoi; cette solution retourne immédiatement lorsqu'elle constate que la nouvelle valeur est déjà présente. Les deux solutions comparent les éléments en itérant. (Chaque déclaration d'affectation de carte effectue au moins une comparaison de clé de carte en interne.) Une carte ne serait utile que si vous pouviez la conserver dans de nombreuses insertions. Si vous le reconstruisez à chaque insertion, tous les avantages sont perdus.

Si vous avez réellement besoin de gérer efficacement de grandes listes, envisagez de les conserver dans un ordre trié. (Je suppose que l'ordre n'a pas d'importance pour vous, car votre première solution est ajoutée au début de la liste et votre dernière solution est ajoutée à la fin.) Si vous gardez toujours les listes triées, vous pouvez utiliser la fonction sort.Recherche pour faire des insertions binaires efficaces.

29
Sonia

distinguer un tableau d'une structure:

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
}

où la structure ici est quelque chose comme: 

type ObjectType struct {
    fieldname1 string
    fieldname2 string
    .........
}

l'objet sera distinct par les champs cochés ici: 

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