如何在非常大的结构中查找 IP 范围?

huangapple go评论84阅读模式
英文:

How to find ip in range in very large struct

问题

我有一个类似下面的结构体,大约有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"
}

上述代码在大约4万个条目时工作正常,但超过这个数量后会变慢。有没有更快的方法来判断一个IP地址是否在结构体中的范围内?

更新:现在只解析一次IP,并将其作为数字存储在结构体中。

英文:

I have a struct like below, with about 100k entires.

I would like to loop over it and check if a ip address is in range.

My current code:

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) &gt;= 0 &amp;&amp; bytes.Compare(iptocheck, elem.IpEnd) &lt;= 0 {
            fmt.Printf(&quot;%v is between %v and %v\n&quot;, IpAddress, elem.IpStart, elem.IpEnd)
            return elem.Id, elem.Descr 
        }
    }
    return &quot;0&quot;, &quot;null&quot;
}

The above works fine with about 40k entires but over that it gets slow. Is there any faster way to find out if a ip address is in range inside my struct?

Update: Now only parsing IP once and storing it as number in struct

答案1

得分: 2

我看到有两个简单的步骤。

  1. 进行一次解析,并将 IP 地址存储为一个单独的数字。
  2. 按照范围的起始位置排序,并使用二分查找算法。
英文:

There are two simple steps I see.

  1. Do the parsing once and store the IP address as a single number.
  2. Order the ranges by start of the range and use binary search.

答案2

得分: 0

作为对@Grzegorz Żur建议的补充,使用二分查找来减少搜索时间,这里是Go语言中的二分查找实现。

首先,什么是二分查找?二分查找将一系列数值划分为两半,并继续缩小搜索范围,直到找到未知值。它是一个经典的“分而治之”算法示例。

该算法返回等于给定值的某个元素的索引(如果有多个这样的元素,则返回任意一个)。当未找到该元素时,还可以返回其“插入点”(如果将其插入数组中,则该值将位于的索引)。

递归方法

func binarySearch(a []float64, value float64, low int, high int) int {
    if high < low {
        return -1
    }
    mid := (low + high) / 2 // 计算两个值的平均值
    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包,你会发现已经实现了基于二分查找的排序算法。所以这可能是最好的选择。

英文:

As a completion of @Grzegorz Żur suggestion to use binary search for reducing the search time, here is a binary search implementation in go.

But first what is binary search? A binary search divides a range of values into halves, and continues to narrow down the field of search until the unknown value is found. It is the classic example of a "divide and conquer" algorithm.

The algorithm returns the index of some element that equals the given value (if there are multiple such elements, it returns some arbitrary one). It is also possible, when the element is not found, to return the "insertion point" for it (the index that the value would have if it were inserted into the array).

The recursive method

func binarySearch(a []float64, value float64, low int, high int) int {
    if high &lt; low {
        return -1
    }
    mid := (low + high) / 2 // calculate the mean of two values
    if a[mid] &gt; value {
        return binarySearch(a, value, low, mid-1)
    } else if a[mid] &lt; value {
        return binarySearch(a, value, mid+1, high)
    }
    return mid
}

The iterative method

func binarySearch(a []float64, value float64) int {
    low := 0
    high := len(a) - 1
    for low &lt;= high {
        mid := (low + high) / 2
        if a[mid] &gt; value {
            high = mid - 1
        } else if a[mid] &lt; value {
            low = mid + 1
        } else {
            return mid
        }
    }
    return -1
}

But if you take a look into the sort package you can observe that there is an already implemented sorting algorithm based on binary search. So probably this would be the best option.

huangapple
  • 本文由 发表于 2016年3月18日 18:26:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/36081938.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定