我有一个类似于下面的结构,大约有10万个人。
我想循环它,检查一下ip地址是否在范围内。
我目前的代码:
type Users struct {
Id string
Descr string
IpStart string
IpEnd string
}
var users []*Users
func LookUpIP(IpAddress string) (string, string) {
iptocheck := net.ParseIP(IpAddress)
for _, elem := range users {
if bytes.Compare(iptocheck, elem.IpStart) >= 0 && bytes.Compare(iptocheck, elem.IpEnd) <= 0 {
fmt.Printf("%v is between %v and %v\n", IpAddress, elem.IpStart, elem.IpEnd)
return elem.Id, elem.Descr
}
}
return "0", "null"
}
上述工作正常,大约40k entires,但结果很慢。有没有更快的方法来确定我的结构中的ip地址是否在范围内?
更新:现在只解析ip一次并将其存储为struct
中的数字答案 0 :(得分:2)
我看到了两个简单的步骤。
答案 1 :(得分:0)
完成@Grzegorz Żur建议使用二进制搜索来缩短搜索时间时,这里是一个二元搜索实现。
但首先是什么是二分搜索?二进制搜索将一系列值分成两半,并继续缩小搜索范围,直到找到未知值。这是“分而治之”算法的典型例子。
算法返回某个元素的索引,该元素等于给定值(如果有多个这样的元素,则返回一些任意元素)。当找不到元素时,也可以返回它的“插入点”(如果它插入到数组中,则该值将具有的索引)。
递归方法
func binarySearch(a []float64, value float64, low int, high int) int {
if high < low {
return -1
}
mid := (low + high) / 2 // calculate the mean of two values
if a[mid] > value {
return binarySearch(a, value, low, mid-1)
} else if a[mid] < value {
return binarySearch(a, value, mid+1, high)
}
return mid
}
迭代方法
func binarySearch(a []float64, value float64) int {
low := 0
high := len(a) - 1
for low <= high {
mid := (low + high) / 2
if a[mid] > value {
high = mid - 1
} else if a[mid] < value {
low = mid + 1
} else {
return mid
}
}
return -1
}
但是如果你看一下sort package,你可以发现已经实现了基于二分搜索的排序算法。所以这可能是最好的选择。