Подтвердить что ты не робот

Перейти: добавить, если уникальный

Есть ли способ проверить фрагменты/карты на наличие значения?

Я хотел бы добавить значение в срез только, если в срезе существует не.

Это работает, но это кажется многословным. Есть ли способ сделать это?

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]
4b9b3361

Ответ 1

Ваш подход займет линейное время для каждой вставки. Лучшим способом было бы использовать map[int]struct{}. В качестве альтернативы вы также можете использовать map[int]bool или что-то подобное, но пустое struct{} имеет то преимущество, что оно не занимает никакого дополнительного места. Поэтому map[int]struct{} является популярным выбором для набора целых чисел.

Пример:

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

Ответ 2

Наиболее эффективным может быть повторение фрагмента и добавление, если вы его не найдете.

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

Это просто и понятно и будет быстрым для небольших списков.

Кроме того, он всегда будет быстрее, чем ваше текущее решение на основе карты. Решение на основе карты выполняет итерацию по всему срезу независимо от того, что; это решение немедленно возвращается, когда обнаруживает, что новое значение уже присутствует. Оба решения сравнивают элементы по мере их повторения. (Каждый оператор присваивания карты, конечно, выполняет по крайней мере одно сопоставление ключей карты внутри.) Карта была бы полезна только в том случае, если вы могли бы поддерживать ее во многих вставках. Если вы перестраиваете его при каждой вставке, все преимущества теряются.

Если вам действительно нужно эффективно обрабатывать большие списки, подумайте о сохранении списков в отсортированном порядке. (Я подозреваю, что заказ не имеет значения для вас, потому что ваше первое решение, добавленное в начале списка, и ваше последнее решение добавляется в конце.) Если вы всегда держите отсортированные списки, то вы можете использовать функцию sort.Search для делают эффективные двоичные вставки.

Ответ 3

различая массив структуры:

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
}

где структура здесь что-то вроде:

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

объект будет различаться по проверенным полям здесь:

if output[j].fieldname1==objs[i].fieldname1 && output[j].fieldname2==objs[i].fieldname2 &&......... {

Ответ 4

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()
}