2012-02-12 17 views
28

¿Hay alguna manera de verificar las porciones/mapas de la presencia de un valor?Ir: Añadir si es único

me gustaría añadir un valor a una rebanada única si lo hace no existen en el sector.

Esto funciona, pero parece detallado. ¿Hay alguna manera mejor 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] 
+1

Re: EDITAR - es la misma historia para cualquier tipo de clave de mapa válido - qué cadena es. – zzzz

+1

Re: EDIT2 - si el orden de los valores en 'newSlice' no importa Y se usará/consumirá utilizando una declaración de rango, entonces su construcción es redundante - simplemente marque las teclas de 'conjunto'. – zzzz

+0

@jnml Gracias por sus comentarios. Estoy almacenando la lista de 'ints' en el almacén de datos de GAE y, para consultar, debe ser un sector (' [] int'). ¿Ese requisito hace que mi técnica inicial sea la mejor opción? Las listas serán pequeñas. –

Respuesta

46

Su enfoque tomaría tiempo lineal para cada inserción. Una mejor manera sería usar un map[int]struct{}. Alternativamente, también puede usar un map[int]bool o algo similar, pero el struct{} vacío 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") 
} 
+0

Gracias por su respuesta. Un par de preguntas: ¿cómo volverías a crear la porción? ¿Hay alguna manera de hacer que esta estrategia funcione con cadenas? Lo siento si esto es obvio, soy nuevo en Go. –

+3

Usaría solo el mapa durante el cálculo (porque tiene un comportamiento O (1) en lugar de O (n)). Después de eso, puede crear un corte y copiar cada valor del mapa. Los elementos tendrán un orden aleatorio después de eso, por lo que es posible que desee ordenarlo.Y puede usar int, float, struct, string y arrays como claves de mapa (al menos en Go1). – tux21b

+0

Gracias específicamente por delinear que las estructuras vacías no ocupan espacio adicional. No sabía esto y usaría map [type] interface {} y asignaría nil a la interfaz. – user1943442

22

más eficiente es probable que se iterando sobre la rebanada y añadiendo si no lo encuentra.

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

Es simple y obvio, y será rápido para las listas pequeñas.

Además, siempre será más rápido que su solución actual basada en mapas. La solución basada en mapas itera sobre toda la división sin importar nada; esta solución regresa inmediatamente cuando descubre que el nuevo valor ya está presente. Ambas soluciones comparan elementos a medida que iteran. (Cada afirmación de asignación de mapa ciertamente hace al menos una comparación de clave de mapa internamente). Un mapa solo sería útil si pudiera mantenerlo en muchas inserciones. Si lo reconstruyes en cada inserción, entonces se pierde toda la ventaja.

Si realmente necesita manejar listas grandes de manera eficiente, considere mantener las listas ordenadas. (Sospecho que el pedido no le importa porque su primera solución se adjuntó al principio de la lista y su última solución se agrega al final.) Si siempre mantiene las listas ordenadas, entonces puede usar la función de búsqueda de clasificación. hacer inserciones binarias eficientes.

+8

"La solución basada en mapas itera sobre toda la división, pase lo que pase": ¿está seguro de que esta es la forma en que funcionan los hash-maps? – Ottokar

+0

@Ottokar, ¿está equivocado? Mucha gente votó a favor, pero no recibió respuesta. –

+1

@FilipBartuzi En realidad, creo que puedo haber entendido mal el significado de esa declaración. Los mapas Hash obviamente no iteran sobre los elementos para encontrar la clave, pero la "solución basada en mapas" para "anexar al corte si es único" pierde su ventaja si tenemos que convertir el corte en mapa y luego el mapa volver a cortar . – Ottokar

Cuestiones relacionadas