Ir: Anexar si único

Hay una forma de comprobar rodajas/mapas de la presencia de un valor?

Me gustaría añadir un valor a una rebanada sólo si no no existen en el sector.

Esto funciona, pero parece detallado. Hay veces mejor manera de hacer esto?

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]
  • Re:EDITAR – es la misma historia para cualquier válido clave del mapa de tipo cadena que es.
  • Re:EDIT2 – si el orden de los valores en ‘newSlice’ no importa Y que será utilizado/consumido uso de una gama de instrucción, a continuación, su construcción es redundante – solo rango de las claves de ‘conjunto’.
  • Gracias por tus comentarios. Estoy almacenar la lista de ints en GAE almacén de datos y para el propósito de la consulta debe ser un slice ( []int ). ¿Que requisito hace que mi primera técnica es la mejor opción? La lista va a ser pequeña.
  • Usted puede evitar el uso de append() (y todas las reasignaciones) por la creación de la creación de un newslice := make([]int, len(set)) en el primer lugar. Si usted hace un montón de tales «contiene la clave …» las pruebas (al menos más de 2), convirtiendo el sector a un mapa[int]struct{} será probablemente mucho más rápido, si no de unos cuantos, el bucle a través de la rebanada directamente es probablemente mejor.
  • Ok, gracias, realmente agradezco que se haya tomado el tiempo para explicar todo esto.
InformationsquelleAutor Kyle Finley | 2012-02-12

4 Kommentare

  1. 84

    Su enfoque tomaría el tiempo lineal para cada inserción. Una mejor manera sería utilizar un map[int]struct{}. Como alternativa, también puede utilizar un map[int]bool o algo similar, pero el vacío struct{} tiene la ventaja de que no ocupa ningún espacio adicional. Por lo tanto map[int]struct{} es una opción popular para un conjunto de números enteros.

    Ejemplo:

    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")
    }
    • Gracias por su respuesta. Un par de preguntas: ¿Cómo volver a crear la rebanada? Es allí una manera de hacer que esta estrategia de trabajo con las cadenas? Lo siento si estos son obvias, soy nuevo en el Ir.
    • Me gustaría utilizar el mapa durante la computación (porque tiene un O(1) comportamiento en lugar de O(n)). Después de eso, usted puede crear un sector y copiar cada uno de los valores del mapa. Los elementos tienen un orden aleatorio después de eso, así que puede que desee ordenar. Y usted puede utilizar int, float, struct, cadenas y matrices como mapa de teclas (al menos en Go1).
    • Gracias específicamente para subrayando que vacía las estructuras de no tomar más espacio. Yo no sabía esto y mapa de uso de[tipo]interfaz{} y podría asignar nil a la interfaz.
    • Yo estaba usando el mapa[tipo]interfaz{} método así, no esto también no tomar más espacio?
  2. 34

    Más eficiente es probable que la iteración sobre el sector y anexando si no lo encuentras.

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

    Es obvia y simple y rápida para listas pequeñas.

    Además, siempre será más rápido que el actual mapa basado en la solución. El mapa basado en la solución recorre toda la rebanada no importa qué, esta solución devuelve de inmediato cuando se encuentre que el nuevo valor ya está presente. Ambas soluciones comparar los elementos ya que iterar. (Cada mapa instrucción de asignación, sin duda, al menos una clave de mapa de comparación internamente.) Un mapa sólo sería útil si usted puede mantener a través de muchas de las inserciones. Si vuelve a generar en cada inserción, a continuación, toda la ventaja se pierde.

    Si usted realmente necesita para manejar eficientemente grandes listas, considerar la posibilidad de mantener las listas ordenadas. (Sospecho que el orden no importa porque tu primera solución que se anexa al principio de la lista y su más reciente solución anexa al final.) Si siempre mantener las listas ordenadas, entonces usted puede utilizar el tipo.Función de búsqueda para hacer eficiente binario inserciones.

    • «El mapa basado en la solución recorre toda la rebanada no importa qué» – ¿estás seguro de que este es el camino hash de los mapas?
    • él está equivocado? Muchas personas upvoted, pero no hay respuesta de la izquierda.
    • En realidad, yo creo que puede haber entendido mal el significado de esa declaración. Hash-mapas, obviamente, no iterar sobre los elementos para encontrar la llave, pero el «mapa basado en la solución» a «agregar a la rebanada de caso único», pierde su ventaja si tenemos que convertir el trozo de mapa y, a continuación, el mapa de nuevo a la corte.
  3. 0

    distincting una matriz de una estructura :

    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
    }

    donde la estructura aquí es algo así como :

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

    el objeto de distintos campos señalados aquí :

    if output[j].fieldname1==objs[i].fieldname1 && output[j].fieldname2==objs[i].fieldname2 &&......... {
  4. 0
    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()
    }

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea