在golang查找两个阵列的交点哪一个更快?

在golang查找两个阵列的交点哪一个更快?,go,set,intersection,Go,Set,Intersection,在golang查找两个阵列的交点哪一个更快 原始可以是一个非常大的列表,目标也可以 original := []string{"test", "test2", "test3"} // n amount of items target := map[string]bool{ "test": true, "test2": true, } for _, val := range original { if target[val] { return true

在golang查找两个阵列的交点哪一个更快

原始可以是一个非常大的列表,目标也可以

original := []string{"test", "test2", "test3"} // n amount of items

target := map[string]bool{
    "test": true,
    "test2": true,
}

for _, val := range original {
    if target[val] {
        return true
    }
}


正如评论中所指出的,您不是在寻找交叉点,而是在寻找
目标中是否存在
原始
的单个实体。也就是说,您的第一个示例是
O(N)
,因为范围是
O(N)
,地图查找是
O(1)
。第二个示例是
O(N^2)
,因为嵌套的范围循环。在没有任何基准测试的情况下,我可以告诉您,第一种方法在时间方面会优越得多(在最坏的情况下)

我对它进行基准测试只是为了展示。原始版本为5000项,目标版本为500项-运行上述两个功能,并使用目标中的所有匹配元素和不匹配元素进行测试:

BenchmarkMapLookup             50000         39756 ns/op
BenchmarkNestedRange             300       4508598 ns/op
BenchmarkMapLookupNoMatch      10000        103441 ns/op
BenchmarkNestRangeNoMatch        300       4528756 ns/op
ok      so  7.072s
这是基准测试代码:

package main

import (
    "math/rand"
    "testing"
    "time"
)

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randSeq(n int) string {
    b := make([]rune, n)
    for i := range b {
        b[i] = letters[rand.Intn(len(letters))]
    }
    return string(b)
}

var (
    original         = []string{}
    target           = []string{}
    targetMap        = map[string]bool{}
    targetNoMatch    = []string{}
    targetMapNoMatch = map[string]bool{}
)

func init() {
    rand.Seed(time.Now().UTC().UnixNano())
    numItems := 5000
    for i := 0; i < numItems; i++ {
        original = append(original, randSeq(10))
    }

    i := rand.Intn(numItems)
    if i >= 4500 {
        i = 4499
    }
    stop := i + 500
    for ; i < stop; i++ {
        target = append(target, original[i])
        targetMap[original[i]] = true
        noMatch := randSeq(9)
        targetNoMatch = append(target, noMatch)
        targetMapNoMatch[noMatch] = true
    }

}

func ON(orig []string, tgt map[string]bool) bool {
    for _, val := range orig {
        if tgt[val] {
            return true
        }
    }
    return false
}

func ON2(orig, tgt []string) bool {
    for _, i := range orig {
        for _, x := range tgt {
            if i == x {
                return true
            }
        }
    }
    return false
}

func BenchmarkMapLookup(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ON(original, targetMap)
    }
}

func BenchmarkNestedRange(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ON2(original, target)
    }
}

func BenchmarkMapLookupNoMatch(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ON(original, targetMapNoMatch)
    }
}

func BenchmarkNestRangeNoMatch(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ON2(original, targetNoMatch)
    }
}
主程序包
进口(
“数学/兰德”
“测试”
“时间”
)
风险值字母=[]符文(“ABCDEFGHIjklmnopqrstuvwxyzabCDEFGHIjklmnopqrstuvxyz”)
func randSeq(n int)字符串{
b:=make([]符文,n)
对于i:=范围b{
b[i]=字母[rand.Intn(len(字母))]
}
返回字符串(b)
}
变量(
原始=[]字符串{}
目标=[]字符串{}
targetMap=map[string]bool{}
targetNoMatch=[]字符串{}
targetMapNoMatch=map[string]bool{}
)
func init(){
rand.Seed(time.Now().UTC().UnixNano())
单位:=5000
对于i:=0;i=4500{
i=4499
}
停止:=i+500
对于;i
正如评论中所指出的,您不是在寻找交叉点,而是在寻找
目标
中是否存在
原始
的单个实体。也就是说,您的第一个示例是
O(N)
,因为范围是
O(N)
,地图查找是
O(1)
。第二个示例是
O(N^2)
,因为嵌套的范围循环。在没有任何基准测试的情况下,我可以告诉您,第一种方法在时间方面会优越得多(在最坏的情况下)

我对它进行基准测试只是为了展示。原始版本为5000项,目标版本为500项-运行上述两个功能,并使用目标中的所有匹配元素和不匹配元素进行测试:

BenchmarkMapLookup             50000         39756 ns/op
BenchmarkNestedRange             300       4508598 ns/op
BenchmarkMapLookupNoMatch      10000        103441 ns/op
BenchmarkNestRangeNoMatch        300       4528756 ns/op
ok      so  7.072s
这是基准测试代码:

package main

import (
    "math/rand"
    "testing"
    "time"
)

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randSeq(n int) string {
    b := make([]rune, n)
    for i := range b {
        b[i] = letters[rand.Intn(len(letters))]
    }
    return string(b)
}

var (
    original         = []string{}
    target           = []string{}
    targetMap        = map[string]bool{}
    targetNoMatch    = []string{}
    targetMapNoMatch = map[string]bool{}
)

func init() {
    rand.Seed(time.Now().UTC().UnixNano())
    numItems := 5000
    for i := 0; i < numItems; i++ {
        original = append(original, randSeq(10))
    }

    i := rand.Intn(numItems)
    if i >= 4500 {
        i = 4499
    }
    stop := i + 500
    for ; i < stop; i++ {
        target = append(target, original[i])
        targetMap[original[i]] = true
        noMatch := randSeq(9)
        targetNoMatch = append(target, noMatch)
        targetMapNoMatch[noMatch] = true
    }

}

func ON(orig []string, tgt map[string]bool) bool {
    for _, val := range orig {
        if tgt[val] {
            return true
        }
    }
    return false
}

func ON2(orig, tgt []string) bool {
    for _, i := range orig {
        for _, x := range tgt {
            if i == x {
                return true
            }
        }
    }
    return false
}

func BenchmarkMapLookup(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ON(original, targetMap)
    }
}

func BenchmarkNestedRange(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ON2(original, target)
    }
}

func BenchmarkMapLookupNoMatch(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ON(original, targetMapNoMatch)
    }
}

func BenchmarkNestRangeNoMatch(b *testing.B) {
    for i := 0; i < b.N; i++ {
        ON2(original, targetNoMatch)
    }
}
主程序包
进口(
“数学/兰德”
“测试”
“时间”
)
风险值字母=[]符文(“ABCDEFGHIjklmnopqrstuvwxyzabCDEFGHIjklmnopqrstuvxyz”)
func randSeq(n int)字符串{
b:=make([]符文,n)
对于i:=范围b{
b[i]=字母[rand.Intn(len(字母))]
}
返回字符串(b)
}
变量(
原始=[]字符串{}
目标=[]字符串{}
targetMap=map[string]bool{}
targetNoMatch=[]字符串{}
targetMapNoMatch=map[string]bool{}
)
func init(){
rand.Seed(time.Now().UTC().UnixNano())
单位:=5000
对于i:=0;i=4500{
i=4499
}
停止:=i+500
对于;i
您将两个切片与一个切片和一个贴图进行比较。它们并不具有可比性,结果会因元素的数量而异。你也没有找到一个交叉点,如果只有一个匹配,就返回true。是的,忘了提到明显的,用你的数据运行两个版本,看看哪个更快!您将两个切片与一个切片和一个贴图进行比较。它们并不具有可比性,结果会因元素的数量而异。你也没有找到一个交叉点,如果只有一个匹配,就返回true。是的,忘了提到明显的,用你的数据运行两个版本,看看哪个更快!