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]
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")
}
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.
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 &&......... {
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()
}