web-dev-qa-db-fra.com

Comment obtenir l'intersection de deux tranches dans le golang?

Existe-t-il un moyen efficace d'obtenir l'intersection de deux tranches dans Go?

slice1 := []string{"foo", "bar","hello"}
slice2 := []string{"foo", "bar"}

intersection(slice1, slice2)
=> ["foo", "bar"]
9
bandi shankar

Oui, il y a différentes façons de s'y prendre. Voici un exemple qui peut être optimisé.

package main

import "fmt"

func intersection(a []string, b []string) (inter []string) {
    // interacting on the smallest list first can potentailly be faster...but not by much, worse case is the same
    low, high := a, b
    if len(a) > len(b) {
        low = b
        high = a
    }

    done := false
    for i, l := range low {
        for j, h := range high {
            // get future index values
            f1 := i + 1
            f2 := j + 1
            if l == h {
                inter = append(inter, h)
                if f1 < len(low) && f2 < len(high) {
                    // if the future values aren't the same then that's the end of the intersection
                    if low[f1] != high[f2] {
                        done = true
                    }
                }
                // we don't want to interate on the entire list everytime, so remove the parts we already looped on will make it faster each pass
                high = high[:j+copy(high[j:], high[j+1:])]
                break
            }
        }
        // nothing in the future so we are done
        if done {
            break
        }
    }
    return
}

func main() {
    slice1 := []string{"foo", "bar", "hello", "bar"}
    slice2 := []string{"foo", "bar"}
    fmt.Printf("%+v\n", intersection(slice1, slice2))
}

Maintenant, la méthode d'intersection définie ci-dessus ne fonctionnera que sur slices de strings, comme dans votre exemple .. Vous pouvez théoriquement créer une définition ressemblant à ceci func intersection(a []interface, b []interface) (inter []interface). ajouter de la latence et rendre votre code plus difficile à lire. Il est probablement plus facile de maintenir et de lire pour écrire une fonction distincte pour chaque type de personne qui compte pour vous.

func intersectionString(a []string, b []string) (inter []string),

func intersectionInt(a []int, b []int) (inter []int),

func intersectionFloat64(a []Float64, b []Float64) (inter []Float64), ..ect

Vous pouvez ensuite créer votre propre package et le réutiliser une fois que vous avez défini comment vous souhaitez le mettre en œuvre.

package intersection

func String(a []string, b []string) (inter []string)

func Int(a []int, b []int) (inter []int)

func Float64(a []Float64, b []Float64) (inter []Float64)
0
reticentroot

Comment obtenir l'intersection de deux tableaux en tant que nouveau tableau?

  • Intersection simple: Comparez chaque élément dans A à chacun dans B (O(n^2))
  • Intersection de hachage: Mettez-les dans une table de hachage (O(n))
  • Intersection triée: triez A et faites une intersection optimisée (O(n*log(n)))

Tous sont mis en œuvre ici

https://github.com/juliangruber/go-intersect

17
KeksArmee

s'il n'y a pas de blanc dans votre []string, vous avez peut-être besoin de ce code simple:

func filter(src []string) (res []string) {
    for _, s := range src {
        newStr := strings.Join(res, " ")
        if !strings.Contains(newStr, s) {
            res = append(res, s)
        }
    }
    return
}

func intersections(section1, section2 []string) (intersection []string) {
    str1 := strings.Join(filter(section1), " ")
    for _, s := range filter(section2) {
        if strings.Contains(str1, s) {
            intersection = append(intersection, s)
        }
    }
    return
}
1
Nevercare

https://github.com/viant/toolbox/blob/master/collections.go

Une autre solution de complexité temporelle O (m + n) utilisant un hashmap. Il a deux différences par rapport aux autres solutions discutées ici.

  • Passer la tranche cible en tant que paramètre à la place de la nouvelle tranche renvoyée
  • Plus rapide à utiliser pour les types couramment utilisés tels que string/int au lieu de réflexion pour tous
1
Tejus Krishna

C'est une meilleure méthode pour l'intersection de deux tranches. La complexité temporelle est trop faible.

Complexité temporelle: O (m + n)

m = longueur de la première tranche.

n = longueur de la deuxième tranche.

func intersection(s1, s2 []string) (inter []string) {
    hash := make(map[string]bool)
    for _, e := range s1 {
        hash[e] = true
    }
    for _, e := range s2 {
        // If elements present in the hashmap then append intersection list.
        if hash[e] {
            inter = append(inter, e)
        }
    }
    //Remove dups from slice.
    inter = removeDups(inter)
    return
}

//Remove dups from slice.
func removeDups(elements []string)(nodups []string) {
    encountered := make(map[string]bool)
    for _, element := range elements {
        if !encountered[element] {
            nodups = append(nodups, element)
            encountered[element] = true
        }
    }
    return
}
1
Rajasankar S